用C#重写Unity3D的Joystick
2014-03-10 10:09
281 查看
/// <summary> //Joystick.cs //Penelope iPhone Tutorial // //Joystick creates a movable joystick (via GUITexture) that //handles touch input, taps, and phases. Dead zones can control //where the joystick input gets picked up and can be normalized.] // //Optionally, you can enable the touchPad property from the editor //to treat this Joystick as a TouchPad. A TouchPad allows the finger //to touch down at any point and it tracks the movement relatively //without moving the graphic. /// </summary> using UnityEngine; using System.Collections; [RequireComponent(typeof(GUITexture))] //A simple class for bounding how far the GUITexture will move public class Boundary { public Vector2 min = Vector2.zero; public Vector2 max = Vector2.zero; } public class Joystick : MonoBehaviour { private static Joystick[] joysticks; //A static collection of all joysticks private static bool enumeratedJoysticks = false; private static float tapTimeDelta = 0.3f; //Time allowed between taps public bool touchPad; //Is this a TouchPad? public Rect touchZone; public Vector2 deadZone = Vector2.zero; //Control when position is output public bool normalize = false; //Normalize output after the dead-done public Vector2 position; //[-1,1] in x,y public int tapCount; //Current tap count private int lastFingerId = -1; //Finger last used for this joystick private float tapTimeWindow; //how much time there is left for a tap to occur private Vector2 fingerDownPos; private float fingerDownTime; private float firstDeltaTime = 0.5f; private GUITexture gui; //Joystick grapic private Rect defaultRect; //Default position / extents of the joystick graphic private Boundary guiBoundary = new Boundary(); //Boundary for joystick graphic private Vector2 guiTouchOffset; //Offset to apply to touch input private Vector2 guiCenter; //Center of joystick // Use this for initialization void Start () { //Cache this component at startup instead of looking up every frame gui = GetComponent<GUITexture>(); //Store the default rect for gui, so we can snap back to it defaultRect = gui.pixelInset; defaultRect.x += transform.position.x * Screen.width;//+ gui.poxelInset.x; //- Screen.width * 0.5; defaultRect.y += transform.position.y * Screen.height;// -Screen.height * 0.5 transform.position = new Vector2 (0, 0); if (touchPad) { //If a texture has been assigend, 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.5f; guiTouchOffset.y = defaultRect.height * 0.5f; //Cache the center of the GUI, since if donesn'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; } } void Disable() { gameObject.SetActive (false); enumeratedJoysticks = false; } void 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) { Color c= gui.color; c.a = 0.025f; gui.color = c; } } bool IsFingerDown() { return (lastFingerId != -1); } public void LatchedFinger(int fingerId) { //If another joystick has latched this finger, then we must releast it if (lastFingerId == fingerId) ResetJoystick(); } // Update is called once per frame void Update () { if (!enumeratedJoysticks) { //Collect all joysticks in the game, so wo can relay finger latching messages joysticks = (Joystick[])FindObjectsOfType(typeof(Joystick)); enumeratedJoysticks = true; } int count = Input.touchCount; //Adjust the tap time window thile it stil available if (tapTimeWindow > 0) tapTimeWindow -= Time.deltaTime; else tapCount = 0; if (count == 0) ResetJoystick(); else { for(int i = 0; i < count; i++) { Touch touch = Input.GetTouch(i); Vector2 guiTouchpos = touch.position - guiTouchOffset; bool 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) { Color c = gui.color; c.a = 0.15f; gui.color = c; 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 foreach(Joystick j in joysticks) { if (j != this) j.LatchedFinger(touch.fingerId); } } if (lastFingerId == touch.fingerId) { //Override the tap count with what the iPone 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 form 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 teh joystick graphic to match where the touch is Rect r = gui.pixelInset; r.x = Mathf.Clamp(guiTouchpos.x, guiBoundary.min.x, guiBoundary.max.x); r.y = Mathf.Clamp(guiTouchpos.y, guiBoundary.min.y, guiBoundary.max.y); gui.pixelInset = r; } 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 float absoluteX = Mathf.Abs(position.x); float 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.0f; } 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); } } }
相关文章推荐
- Unity3D 双摇杆 c# JoyStick 实现自己的双摇杆
- Unity3D 官方Joystick改为C#版本
- Unity3D 摇杆Joystick C#版本
- 关于c#的unity3d中双问号操作符(??)无法正确判断null值的问题
- c#中获取URL重写前的原始地址
- C# 类(8) 覆盖与重写
- Unity3D中C#编写脚本
- 【c#】重写和重载
- VS2003 C#:重写键盘响应事件、动态创建控件、创建线程、在线程中使用委托在界面显示数据
- [原创]C#中的继承、重写、覆盖、多态、virtual override 以及其他
- C#中的隐藏和重写
- Unity3D的JS和C#脚本互调
- C# 事件和Unity3D
- C#继承类重写与隐藏基类方法的区别
- C# TabControl重写
- C#虚方法、抽象类、方法重写
- Unity3d C# 创建 物体
- C#...何时需要重写ToString()方法?
- Unity3D中创建按钮的实例代码(C#代码)
- c#调试问题Dispose(bool) 没有找到适合的方法来重写【搜藏】