【问题标题】:How to Convert Keyboard to Touch controller如何将键盘转换为触摸控制器
【发布时间】:2019-04-18 21:44:36
【问题描述】:

美好的一天,我是 Unity c# 的新手。有谁知道如何将我的二维自上而下汽车控制器脚本从键盘转换为触摸按钮。我需要为我的 2d 自上而下汽车配备一个带有中断、后退、加速和左右按钮的触摸按钮。

我的代码基于街机风格的汽车游戏。

    float speedForce = 15f;
    float torqueForce = -200f;
    float driftFactorSticky = 0.9f;
    float driftFactorSlippy = 1;
    float maxStickyVelocity = 2.5f;
    float minSlippyVelocity = 1.5f; // <--- Exercise for the viewer

    // Use this for initialization
    void Start () 
    {

    }

    void Update() 
    {
        // check for button up/down here, then set a bool that you will use in FixedUpdate
    }

    // Update is called once per frame
    void FixedUpdate () 
    {
        Rigidbody2D rb = GetComponent<Rigidbody2D>();

        Debug.Log(RightVelocity().magnitude);

        float driftFactor = driftFactorSticky;
        if(RightVelocity().magnitude > maxStickyVelocity) {
            driftFactor = driftFactorSlippy;
        }

        rb.velocity = ForwardVelocity() + RightVelocity()*driftFactor;

        if(Input.GetButton("Accelerate")) {
            rb.AddForce( transform.up * speedForce );

            // Consider using rb.AddForceAtPosition to apply force twice, at the position
            // of the rear tires/tyres
        }
        if(Input.GetButton("Brakes")) {
            rb.AddForce( transform.up * -speedForce/2f );

            // Consider using rb.AddForceAtPosition to apply force twice, at the position
            // of the rear tires/tyres
        }

        // If you are using positional wheels in your physics, then you probably
        // instead of adding angular momentum or torque, you'll instead want
        // to add left/right Force at the position of the two front tire/types
        // proportional to your current forward speed (you are converting some
        // forward speed into sideway force)
        float tf = Mathf.Lerp(0, torqueForce, rb.velocity.magnitude / 2);
        rb.angularVelocity = Input.GetAxis("Horizontal") * tf;
    }

    Vector2 ForwardVelocity() 
    {
        return transform.up * Vector2.Dot( GetComponent<Rigidbody2D>().velocity, transform.up );
    }

    Vector2 RightVelocity() 
    {
        return transform.right * Vector2.Dot( GetComponent<Rigidbody2D>().velocity, transform.right );
    }
}

【问题讨论】:

  • 似乎它只是用于触摸我真正需要的是我的汽车被控制在我的画布上的 UI 按钮。但无论如何谢谢!它可能有用。
  • 哦,你应该改写标题并提出一些问题......听起来你是在问 Touch 而不是 UI.Button

标签: c# unity3d 2d


【解决方案1】:

而不是

if(Input.GetButton("Accelerate")) 
{
    rb.AddForce( transform.up * speedForce );
}
if(Input.GetButton("Brakes")) 
{
    rb.AddForce( transform.up * -speedForce/2f );
}

rb.angularVelocity = Input.GetAxis("Horizontal") * tf;

只需检查一些布尔值并为它们设置相应的设置方法(您需要那些能够通过 UnityEvents 调用它们的方法):

private bool acceleratePressed;
private bool brakePressed;
private bool leftPressed;
private bool rightPressed;

public void SetAccelerate(bool pressed)
{
    acceleratePressed = pressed;
}

public void SetBrake(bool pressed)
{
    brakePressed = pressed;
}

public void SetRightPressed(bool pressed)
{
    rightPressed = pressed;
}

public void SetLeftPressed(bool pressed)
{
    leftPressed = pressed;
}

private void FixedUpdate()
{
    if(acceleratePressed) 
    {
        rb.AddForce( transform.up * speedForce );
    }
    if(brakePressed)
    {
        rb.AddForce( transform.up * -speedForce/2f );
    }

    var leftRight = 0;
    if(leftPressed && !rightPressed)
    {
        leftRight = -1;
    }
    else if(!leftPressed && rightPressed)
    {
        leftRight = 1;
    }

    // If you are using positional wheels in your physics, then you probably
    // instead of adding angular momentum or torque, you'll instead want
    // to add left/right Force at the position of the two front tire/types
    // proportional to your current forward speed (you are converting some
    // forward speed into sideway force)
    float tf = Mathf.Lerp(0, torqueForce, rb.velocity.magnitude / 2);
    rb.angularVelocity = leftRight * tf;
}

不幸的是,Unity UI.Button 没有向下或向上转发按钮的方法......只有onClick

但是您可以非常轻松地自行实施其他事件!你可以使用IPointerDownHandlerIPointerUpHandler&IPointerExitHandler接口和自定义UnityEvents

我不喜欢从 UI.Button 继承(有些人可能更喜欢这样做),而是在单独的组件中添加额外的行为。

还有其他方法可以准确地实现它,但我喜欢保持可重用,所以我会像这样使用它

[RequireComponent((typeof(Button)))]
public class DownUpButtonEnhancement : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler
{
    private Button _button;

    public UnityEvent OnButtonDown;
    public UnityEvent OnButtonUp;

    private void Awake()
    {
        _button = GetComponent<Button>();
    }

    //Detect current clicks on the GameObject (the one with the script attached)
    public void OnPointerDown(PointerEventData pointerEventData)
    {
        if (!_button.interactable) return;

        OnButtonDown?.Invoke();
    }

    //Detect if clicks are no longer registering
    public void OnPointerUp(PointerEventData pointerEventData)
    {
        OnButtonUp?.Invoke();
    }

    // Detect if pointer leaves the object
    public void OnPointerExit(PointerEventData eventData)
    {
        // additionally reset if pointer leaves button while pressed
        OnButtonUp?.Invoke();
    }
}

把它放在你的两个 UI Buttons 上,并按照与 onClickButton 相同的方式配置 OnButtonDownOnButtonUp 回调:

  1. 将带有移动脚本的 GameObject 拖入
  2. 选择应在按下按钮的每一帧调用的相应方法。
  3. 对于OnButtonDown,传入true(选中复选框)对于OnButtonUp,传入false。

然后在游戏中,您可以看到现在 MoveController 脚本的相应布尔值在按下按钮时启用,并且如果在按下按钮的同时离开按钮,则另外重置

【讨论】:

  • 我有一个错误 Assets/Scripts/CarEngine.cs(32,13)​​: error CS1644: Feature `null propagating operator' cannot be used 因为它不是 C# 4.0 语言规范的一部分
  • 哦,好吧..要么切换到.Net 4.X,要么简单地将每个OnButtonDown?.Invoke();替换为if(OnButtonDown != null) OnButtonDown.Invoke();
  • 非常感谢!但我还有一个问题,它只适用于加速和刹车按钮吗?有左右触摸键吗?
  • 您在该按钮上写的文本标签以及它在单击时执行的操作完全可以由您调整(您也可以使用没有任何文本而是图标的仅图像按钮)还是我得到了问题错了吗?
  • 不,先生。我还想要的是用于移动的左右按钮以及后退控件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
  • 2015-08-08
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多