【问题标题】:Making object slide to one direction使物体向一个方向滑动
【发布时间】:2018-11-19 03:22:34
【问题描述】:

我想让我的 Rigidbody 对象向右或向左滑动。

例如,如果他在 0 X,他会向一个方向滑动 1,然后在这个方向停止并停止。

通过施加力,物体会一直朝那个方向移动,我想让物体移动,然后停止。

编辑 这是我尝试过的

void Update() {

    if (Input.GetKeyDown("d") && !isMoving) {
        StartCoroutine(MoveToPos(Vector3.right));
    }

    if (Input.GetKeyDown("a") && !isMoving) {
        StartCoroutine(MoveToPos(Vector3.left));
    }
}

public IEnumerator MoveToPos(Vector3 direction) {
    isMoving = true;
    var t = 0f;
    var startPosition = transform.position;
    var value = direction == Vector3.right? 1 : -1;
    while (t < 1f) {
        t += 0.05f;
        var endPosition = transform.position;
        endPosition.x = startPosition.x + value * t;
        transform.position = Vector3.Lerp(transform.position, endPosition, t);
        Debug.Log(player.position);
        yield return null;
    }
    isMoving = false;
}

但遗憾的是它的动画非常难看,对象很快就卡到了最终位置,看起来不像对象滑动然后停在那里。就像没有加速和减速一样。

编辑 2

我尝试调整值并进行减速运动。有点工作,但我想它仍然需要改进。

public IEnumerator MoveToPos(Vector3 direction) {
    isMoving = true;
    var t = 0.0;
    var startPosition = transform.position;
    var value = direction == Vector3.right ? 1 : -1;
    while (t < 1) {
        if (t < 0.5) t += 0.1;
        else t += 0.03125;
        Debug.Log(t);
        var endPosition = transform.position;
        endPosition.x = startPosition.x + value * (float)t;
        transform.position = Vector3.Lerp(transform.position, endPosition, (float)t);
        yield return null;
    }
    isMoving = false;
}

我猜调整加速度和减速度的值会使动画更流畅。

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    简单的方法是这样的:

    void Update()
        {
            if(Input.GetKeyDown(KeyCode.A))
                transform.Translate(Vector3.right * 1);
        }
    

    作为“A Key”移动对象的条件,并将Vector3.right 更改为对应方向(左、上、下...)

    但我建议使用 Lerp 函数来赋予它更逼真的运动: https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html

    【讨论】:

    • Lerp 函数与 IEnumerator 一起工作,但遗憾的是,该运动非常难看。对象滑动到该位置,然后捕捉到最终位置。
    • 那你想做什么?
    • 平滑的东西。从起点到终点有加速和声明。
    【解决方案2】:

    你的代码有几个错误:

    1。不要使用固定数字增加时间(t 变量)。为此使用Time.deltaTime

    2。不要使用transform 移动带有刚体的游戏对象。所以,不要做transform.position = xxxtransform.Translate(xxx)。移动刚体对象时,使用Rigidbody.MovePosition 函数。

    3在使用Rigidbody.MovePosition 函数移动刚体时,您应该在刚体上启用isKinematic,因为它会使其非常平滑。

    最后,要让它在移动完成后立即停止,请将velocityangularVelocity 设置为零。

    你的固定新功能:

    bool isMoving = false;
    IEnumerator MoveToPos(Rigidbody targetObject, Vector3 direction, float duration, float units = 1f)
    {
        isMoving = true;
        targetObject.isKinematic = true;
    
        float counter = 0;
    
        //Get the current position of the object to be moved
        Vector3 startPos = targetObject.position;
        //Get destination position
        Vector3 toPosition = startPos + direction * units;
    
        while (counter < duration)
        {
            counter += Time.deltaTime;
            //targetObject.position = Vector3.Lerp(startPos, toPosition, counter / duration);
            Vector3 newPos = Vector3.Lerp(startPos, toPosition, counter / duration); ;
            targetObject.MovePosition(newPos);
            yield return null;
        }
    
        targetObject.isKinematic = false;
        //Stop right away
        targetObject.velocity = Vector3.zero;
        targetObject.angularVelocity = Vector3.zero;
        isMoving = false;
    }
    

    用法:

    Rigidbody rb = GetComponent<Rigidbody>();
    StartCoroutine(MoveToPos(rb, Vector3.right, 3f, 1f));
    

    【讨论】:

    • 我还没有尝试过,但我猜想停止是立即的,而不是物理基础。最好找到能给物体一个小推力的东西,足以让它到达另一边,同时随着时间的推移而阻尼。将对象捕捉到最终位置看起来非常难看,就像您推动对象一样,但它在中途卡住并固定。
    • “将对象捕捉到结束位置” 不,这不是我的代码正在做的事情。它找到结束位置,将其分成几块,然后平滑地处理每一块。在制作进一步的 cmets 之前,请尝试答案中的内容,以便您的 cmets 反映您遇到的实际问题。如果你想让滑动由物理引擎控制,给方向加力:Rigidbody.AddForce(direction * speed)
    • 对象在 X 轴上滑动,但在其他轴上冻结。我的对象一直在 Z 轴上向前移动,所以在其他轴上冻结它是一个非常糟糕的举动。
    猜你喜欢
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多