- Home /
Joystick / Button
Hi,
Im using the Joystick.js script from the penelope iPhone Tutorial. I have a script called TwinStick.js that Im using to access the Joystick script to make my player move and shoot.
I would like to create another button and use this 3rd button to simply print a message when clicked and this is where Im kind of lost. I don't want this 3rd button to move like a Joystick so I enabled TouchPad in the inspector. But how would I print a message by clicking this 3rd button (var spellButton : Joystick) it seems that the Joystick script is registering all inputs and touches So I figured I might as well use it but I dont know how to ask for the hitTest.
Can someone give me a code hint to get the 3rd button to print("3rd button clicked, spell"); from the variable spellButton.
Here is the TwinStick Script which moves my player using the 2 joysticks (one for movement the other for firing) along with a bunch of commented out stuff that I couldn't get to work trying to get a print out for the 3rd button. And I'll put the Joystick script from Penelope below as well.
TwinStick.js
var spellButton : Joystick;;//TouchPad enabled in the inspector so graphic dosent move for animation spell button
var leftStick: Joystick;
var rightStick: Joystick;
var moveSpeed : float = 3.0;
var projectile : Transform;
var shootPos : Transform;
var projectileSpeed : int = 2000;
private var nextFireTime : float; //when can we shoot again
var rapidFireDelay : float = 0.5; //delay between shots
var reloadTime : float = 1.0; //time it takes to reload :)
private var theClip : int; //ammo remaining in clip
var ammoPerClip : int = 5;
var shooting : boolean = false;
function Update()
{
//spellButton//somehow register touch through joystick script???
/*
if(spellButton.HitTest(touch.position))
{
print("Spell Button Enabled");
}
*/
//TouchTarget();
/*
var count : int = Input.touchCount;
if( count >= 1)
{
var touch : Touch = Input.GetTouch(0);
if (spellButton.HitTest( touch.position ) )
{
print("Spell");
}
}
*/
////////////////Moves the Player & rotates him /////////////////////////////////
var lh : float = leftStick.position.x;//("LeftStickHorizontal"); X
var lv : float = leftStick.position.y;//("LeftStickVertical"); Y
var rh : float = rightStick.position.x;//("RightStickHorizontal"); X
var rv : float = rightStick.position.y;//("RightStickVertical"); Y
//LeftStick
transform.position += Vector3(lh, 0.0, lv).normalized * moveSpeed
* Time.deltaTime;
//RightStick
transform.LookAt(transform.position + Vector3(rh, 0.0, rv));
////////////////End Player Movement ////////////////////////////////////////////
//shooting just to turn it off to test other weapon
if(shooting)
{
if(rightStick.position.x || rightStick.position.y > 0 )//stickposition greater than 0 fire
{
if (nextFireTime <= Time.time)
{
nextFireTime = Time.time + rapidFireDelay;
Fire();
}
}
}
}
function Fire()
{
theClip--;
if(theClip < 0)
{
Reload();
}
else
{
//var bullet = PoolManager.Pools["Shapes"].Spawn(projectile, shootPos.transform.position, shootPos.transform.rotation);
var bullet = Instantiate(projectile, shootPos.transform.position, shootPos.transform.rotation);
bullet.rigidbody.AddForce(bullet.transform.forward * projectileSpeed);
bullet.name = "iBullet";
}
}
function Reload()
{
theClip = ammoPerClip;
nextFireTime = Time.time + reloadTime;
}
/*
function TouchTarget()
{
var count : int = Input.touchCount;
if(count >= 1)
{
for (var i = 0; i < Input.touchCount; ++i)
{
if (Input.GetTouch(i).phase == TouchPhase.Began)
{
if(spellButton.HitTest)
{
print("touching");
}
}
}
}
}
*/
Here is the Joystick.js
#pragma strict
@script RequireComponent( GUITexture )
// A simple class for bounding how far the GUITexture will move
class Boundary
{
var min : Vector2 = Vector2.zero;
var max : Vector2 = Vector2.zero;
}
static private var joysticks : Joystick[]; // A static collection of all joysticks
static private var enumeratedJoysticks : boolean = false;
static private var tapTimeDelta : float = 0.3; // Time allowed between taps
var touchPad : boolean; // Is this a TouchPad?
var touchZone : Rect;
var deadZone : Vector2 = Vector2.zero; // Control when position is output
var normalize : boolean = false; // Normalize output after the dead-zone?
var position : Vector2; // [-1, 1] in x,y
var tapCount : int; // Current tap count
private var lastFingerId = -1; // Finger last used for this joystick
private var tapTimeWindow : float; // How much time there is left for a tap to occur
private var fingerDownPos : Vector2;
private var fingerDownTime : float;
private var firstDeltaTime : float = 0.5;
private var gui : GUITexture; // Joystick graphic
private var defaultRect : Rect; // Default position / extents of the joystick graphic
private var guiBoundary : Boundary = Boundary(); // Boundary for joystick graphic
private var guiTouchOffset : Vector2; // Offset to apply to touch input
private var guiCenter : Vector2; // Center of joystick
function Start()
{
// Cache this component at startup instead of looking up every frame
gui = GetComponent( GUITexture );
// Store the default rect for the gui, so we can snap back to it
defaultRect = gui.pixelInset;
defaultRect.x += transform.position.x * Screen.width;// + gui.pixelInset.x; // - Screen.width * 0.5;
defaultRect.y += transform.position.y * Screen.height;// - Screen.height * 0.5;
transform.position.x = 0.0;
transform.position.y = 0.0;
if ( touchPad )
{
// If a texture has been assigned, then use the rect ferom the gui as our touchZone
if ( gui.texture )
touchZone = defaultRect;
}
else
{
// This is an offset for touch input to match with the top left
// corner of the GUI
guiTouchOffset.x = defaultRect.width * 0.2;//was 0.5 so the buttons dont go off screen
guiTouchOffset.y = defaultRect.height * 0.2;//was 0.5 so the buttons dont go off screen
// Cache the center of the GUI, since it doesn't change
guiCenter.x = defaultRect.x + guiTouchOffset.x;
guiCenter.y = defaultRect.y + guiTouchOffset.y;
// Let's build the GUI boundary, so we can clamp joystick movement
guiBoundary.min.x = defaultRect.x - guiTouchOffset.x;
guiBoundary.max.x = defaultRect.x + guiTouchOffset.x;
guiBoundary.min.y = defaultRect.y - guiTouchOffset.y;
guiBoundary.max.y = defaultRect.y + guiTouchOffset.y;
}
}
function Disable()
{
gameObject.active = false;
enumeratedJoysticks = false;
}
function ResetJoystick()
{
// Release the finger control and set the joystick back to the default position
gui.pixelInset = defaultRect;
lastFingerId = -1;
position = Vector2.zero;
fingerDownPos = Vector2.zero;
if ( touchPad )
gui.color.a = 0.025;
}
function IsFingerDown() : boolean
{
return (lastFingerId != -1);
}
function LatchedFinger( fingerId : int )
{
// If another joystick has latched this finger, then we must release it
if ( lastFingerId == fingerId )
ResetJoystick();
}
function Update()
{
if ( !enumeratedJoysticks )
{
// Collect all joysticks in the game, so we can relay finger latching messages
joysticks = FindObjectsOfType( Joystick ) as Joystick[];
enumeratedJoysticks = true;
}
var count = Input.touchCount;
// Adjust the tap time window while it still available
if ( tapTimeWindow > 0 )
tapTimeWindow -= Time.deltaTime;
else
tapCount = 0;
if ( count == 0 )
ResetJoystick();
else
{
for(var i : int = 0;i < count; i++)
{
var touch : Touch = Input.GetTouch(i);
var guiTouchPos : Vector2 = touch.position - guiTouchOffset;
var shouldLatchFinger = false;
if ( touchPad )
{
if ( touchZone.Contains( touch.position ) )
shouldLatchFinger = true;
}
else if ( gui.HitTest( touch.position ) )
{
shouldLatchFinger = true;
}
// Latch the finger if this is a new touch
if ( shouldLatchFinger && ( lastFingerId == -1 || lastFingerId != touch.fingerId ) )
{
if ( touchPad )
{
gui.color.a = 0.15;
lastFingerId = touch.fingerId;
fingerDownPos = touch.position;
fingerDownTime = Time.time;
}
lastFingerId = touch.fingerId;
// Accumulate taps if it is within the time window
if ( tapTimeWindow > 0 )
tapCount++;
else
{
tapCount = 1;
tapTimeWindow = tapTimeDelta;
}
// Tell other joysticks we've latched this finger
for ( var j : Joystick in joysticks )
{
if ( j != this )
j.LatchedFinger( touch.fingerId );
}
}
if ( lastFingerId == touch.fingerId )
{
// Override the tap count with what the iPhone SDK reports if it is greater
// This is a workaround, since the iPhone SDK does not currently track taps
// for multiple touches
if ( touch.tapCount > tapCount )
tapCount = touch.tapCount;
if ( touchPad )
{
// For a touchpad, let's just set the position directly based on distance from initial touchdown
position.x = Mathf.Clamp( ( touch.position.x - fingerDownPos.x ) / ( touchZone.width / 2 ), -1, 1 );
position.y = Mathf.Clamp( ( touch.position.y - fingerDownPos.y ) / ( touchZone.height / 2 ), -1, 1 );
}
else
{
// Change the location of the joystick graphic to match where the touch is
gui.pixelInset.x = Mathf.Clamp( guiTouchPos.x, guiBoundary.min.x, guiBoundary.max.x );
gui.pixelInset.y = Mathf.Clamp( guiTouchPos.y, guiBoundary.min.y, guiBoundary.max.y );
}
if ( touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled )
ResetJoystick();
}
}
}
if ( !touchPad )
{
// Get a value between -1 and 1 based on the joystick graphic location
position.x = ( gui.pixelInset.x + guiTouchOffset.x - guiCenter.x ) / guiTouchOffset.x;
position.y = ( gui.pixelInset.y + guiTouchOffset.y - guiCenter.y ) / guiTouchOffset.y;
}
// Adjust for dead zone
var absoluteX = Mathf.Abs( position.x );
var absoluteY = Mathf.Abs( position.y );
if ( absoluteX < deadZone.x )
{
// Report the joystick as being at the center if it is within the dead zone
position.x = 0;
}
else if ( normalize )
{
// Rescale the output after taking the dead zone into account
position.x = Mathf.Sign( position.x ) * ( absoluteX - deadZone.x ) / ( 1 - deadZone.x );
}
if ( absoluteY < deadZone.y )
{
// Report the joystick as being at the center if it is within the dead zone
position.y = 0;
}
else if ( normalize )
{
// Rescale the output after taking the dead zone into account
position.y = Mathf.Sign( position.y ) * ( absoluteY - deadZone.y ) / ( 1 - deadZone.y );
}
}
Greatly Appreciated! Sorry for the long post Im just trying to figure this out.
Answer by G54 · Feb 11, 2012 at 06:25 PM
I would personally just do the below. The stuff in the update function detects the click and the stuff in the OnGUI draws the texture
function Update(){
for(var i: int = 0;i < count; i++)
{
var touch : Touch = Input.GetTouch(i);
if(Rect(0, 0, 100, 100).Contains(touch.position) && touch.phase == TouchPhase.Began)
{
print("3rd button clicked, spell");
}
}}
function OnGUI(){GUI.DrawTexture(Rect(0,540,100,100), texture);}
Answer by michael777 · Feb 11, 2012 at 07:15 PM
Its strange that the texture is not where the button is? Its really close to the left joystick but I do think its working :) Once I get the Rect to match the Texture position I'll know for sure.
var btnTexture : Texture;
var leftStick: Joystick;
var rightStick: Joystick;
function Update()
{
var count : int = Input.touchCount;
for(var i: int = 0;i < count; i++)
{
var touch : Touch = Input.GetTouch(i);
if(Rect(0, 0, 100, 100).Contains(touch.position) && touch.phase == TouchPhase.Began)
{
print("3rd button clicked, spell");
}
}
}
function OnGUI()
{
GUI.DrawTexture(Rect(0,0,100,100), btnTexture);
}
So I looked up Rect and found this on the Scripting reference
// prints inside when mouse is in lower left corner
function Update () {
var rect = Rect (0, 0, 150, 150);
if (rect.Contains(Input.mousePosition))
print("Inside");
}
wouldn't it print when the mouse is in the top-left corner? I thought it was (Rect(position x, position y, width x, height y)) but the scripting reference is saying lower left. So Im a little confused on this? After using GUI buttons for so long.
Sorry forgot to explain! For some reason the GUI Rect coordinate system and the Touch Rect system are a little different. The Touch Rect system has the the top coordinate flipped for example in GUI Rect(0,0,10,10) creates something in the top left corner of the screen, but Touch Rect(0,0,10,10) is the BOTTO$$anonymous$$ left of the screen.
so u need to change the if(Rect(0, 0, 100, 100).Contains(touch.position) to if(Rect(0, Screen.height - 100, 100, 100).Contains(touch.position) to have the detection be in the same spot as the GUI texture
Answer by michael777 · Feb 11, 2012 at 07:32 PM
Seriously Appreciated G54 !!!
I think I have a new understanding and a much easier way of doing things :) You are awesome! thank you very very very much! it works great! The penelope tutorials are nice but confusing for a newbie well not confusing overwhelming and I understand we all have different learning levels though.
Thanks a million! It works AWESOME.
your welcome. I always try to help when I can since I was like you about 8 months ago. I also had the same issue with the GUI rect vs Touch rect thing a while back. Good luck with Unity!
Your answer
Follow this Question
Related Questions
Joystick Zone + Screen-swipe touch input clash. Solution??? 1 Answer
Issue with Input.GetMouseButton (0) on mobile (iPhone) 2 Answers
Input.GetAxis("Vertical") on touch devices. 2 Answers
Android Multi-Touch Issue 2 Answers
Joystick C# change touch zone? 0 Answers