【问题标题】:Player movement with voice input (transform.Translate) not working as intented使用语音输入 (transform.Translate) 的玩家移动未按预期工作
【发布时间】:2020-07-14 17:12:56
【问题描述】:

我已经成功地在 Unity 中创建了我的第一个游戏,让用户可以在表面移动。它工作得很好。但是,我现在也希望能够通过语音输入移动播放器。当玩家听到jump 这个词时,他们会跳起来,但例如当玩家听到go 时向前移动,我只是使用了transform.Translate(2, 0, 0)。这会使玩家向前移动,但它并不关心表面如何,例如即使前方有斜坡,它也会穿过物体或直线移动。用键盘移动没有任何问题。

这是我的代码:

public class PlayerMovement : MonoBehaviour {

        
        public CharacterController2D controller;
        public Animator animator;

        public float runSpeed = 40f;

        float horizontalMove = 0f;

        bool jump = false;

        bool crouch = false;

        private KeywordRecognizer keywordRecognizer;

        private Dictionary<string, Action> actions = new Dictionary<string, Action>();


        void Start()
        {
            actions.Add("Go", Go);
            actions.Add("up", Up);
            actions.Add("back", Back);

            keywordRecognizer = new KeywordRecognizer(actions.Keys.ToArray());
            keywordRecognizer.OnPhraseRecognized += RecognizedSpeech;
            keywordRecognizer.Start();

        }


        private void RecognizedSpeech(PhraseRecognizedEventArgs speech)
        {
            Debug.Log(speech.text);
            actions[speech.text].Invoke();

        }



    // Update is called once per frame

    void Update () {

            horizontalMove =  Input.GetAxisRaw("Horizontal") * runSpeed;

            animator.SetFloat("Speed", Mathf.Abs(horizontalMove));

            if (Input.GetButtonDown("Jump")) {
                jump = true;
                animator.SetBool("IsJumping",true);
            }


            if (Input.GetButtonDown("Crouch")){
                crouch = true;
            } else if (Input.GetButtonUp("Crouch")){
            crouch = false;
            }

                }
          



        public void OnLanding (){
            animator.SetBool("IsJumping", false);
        }


        void FixedUpdate()
        {
            // Move our character
            controller.Move(horizontalMove * Time.deltaTime, crouch, jump);
            jump = false;

    }


    void Go()
    {
        transform.Translate(2, 0, 0);
    }

    void Back()
    {
        transform.Translate(-2, 0, 0);
    }

    void Up()
    {
        jump = true;
        animator.SetBool("IsJumping", true);
    }

}

我需要进行哪些更改才能让玩家通过语音输入真正按预期移动。

非常感谢,如果是基本问题,请见谅!

【问题讨论】:

  • 不同之处在于,例如在Go transform.Translate(2, 0, 0); "teletransports" 中,关于 2 的对象将单位固定到右侧,而controller.Move(horizontalMove * Time.deltaTime, crouch, jump); 随着时间的推移以horizontalMove 单位/秒 平滑移动对象
  • 好的,但是为什么我不能在Go 方法中使用controller.Move(horizontalMove * Time.deltaTime, crouch, jump);

标签: c# unity3d


【解决方案1】:

不同之处在于,例如在Go transform.Translate(2, 0, 0); "teletransports" 中,关于 2 的对象将单位固定到右侧,而controller.Move(horizontalMove * Time.deltaTime, crouch, jump); 随着时间的推移以horizontalMove 单位/秒平滑移动对象。

还请注意,您不应将通过TransformRigidbody(/Rigidbody2D) 混合使用......这会破坏物理原理。

你可以简单地使用

public void Go
{
    controller.Move(runSpeed * 2, crouch, jump);
}

public void Back
{
    controller.Move(runSpeed * -2, crouch, jump);
}

不过,我会使用Coroutine,它模拟按钮在语音命令后按下一段时间,然后将FixUpdate 中的移动留在原地,例如

// How long shall the character move into the direction after voice command?
[SerializeField] private float voicePressDuration = 1f;

private bool isVoiceCommand;
private Coroutine voiceRoutine;

void Update () 
{
    if(!isVoiceCommand) horizontalMove =  Input.GetAxisRaw("Horizontal") * runSpeed;

    animator.SetFloat("Speed", Mathf.Abs(horizontalMove));

    if (Input.GetButtonDown("Jump")) 
    {
        jump = true;
        animator.SetBool("IsJumping",true);
    }

    if (Input.GetButtonDown("Crouch"))
    {
        crouch = true;
    } 
    else if (Input.GetButtonUp("Crouch"))
    {
        crouch = false;
    }
}

void Go()
{
    if(voiceRoutine != null)
    {
        // evtl interrupt an already running routine
        StopCoroutine(voiceRoutine);
    } 

    voiceRoutine = StartCoroutine(ProcessVoiceMove(runSpeed));
}

void Back()
{
    if(voiceRoutine != null)
    {
        // evtl interrupt an already running routine
        StopCoroutine(voiceRoutine);
    } 

    voiceRoutine = StartCoroutine(ProcessVoiceMove(-runSpeed));
}

private IEnuermator ProcessVoiceMove(float value)
{
    isVoiceCommand = true;
    horizontalMove = value;

    yield return new WaitForSeconds(voicePressDuration);

    isVoiceCommand = false;
}

在说例如之后这样Go 对象将向前移动一秒钟或您在voicePressDuration 中配置的任何内容。

【讨论】:

  • 这是一个Coroutine .. 上面是一个private Coroutine voiceRoutine;
【解决方案2】:

通过 CharacterController2D 移动您的玩家,而不是通过 Translate,因为这不允许物理检测碰撞。

类似这样的:

void Go()
{
   controller.Move(2, crouch, jump);
}

void Back()
{
   controller.Move(-2, crouch, jump);
}

【讨论】:

  • 它给出了cannot convert from UnityEngine.Vector3 to float。 move 方法看起来像这样public void Move(float move, bool crouch, bool jump)。有没有办法将Vector3.right 转换为浮动?
  • 你从哪里得到 CharacterController2D?来自这个 repo - github.com/prime31/CharacterController2D?
  • 不,它不是同一个仓库。我遵循了其他一些教程
  • 我改了答案,看看这个
  • 如果我这样做,玩家就会呆在那里。它什么都不做:(
猜你喜欢
  • 2020-11-29
  • 2013-01-11
  • 2016-08-15
  • 2015-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多