如果射线投射未命中,如何将对象移回其初始位置?

时间:2019-08-26 23:17:28

标签: c# unity3d

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OnMouseOverEvent : MonoBehaviour
{
    public float duration;
    public string tag;
    public Vector3 startPos;
    public Vector3 endPos;
    public float distancetoMove = 1f;
    public float lerpTime = 5;

    private float currentLerpTime = 0;

    private void Start()
    {
        startPos = transform.position;
        endPos = transform.position - Vector3.forward * distancetoMove;
    }

    private void Update()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit, 100))
        {
            if (hit.transform.tag == tag)
            {
                currentLerpTime += Time.deltaTime;
                if(currentLerpTime >= lerpTime)
                {
                    currentLerpTime = lerpTime;
                }

                float Perc = currentLerpTime / lerpTime;
                transform.position = Vector3.Lerp(startPos, endPos, Perc);
            }
            else
            {
                transform.position = Vector3.Lerp(endPos, startPos, Perc);
            }
        }
    }
}

如果被物体击中,它会缓慢平稳地向前移动,但是我希望射线投射持续击中该物体时,它会向前移动;如果到一定距离,只要它被物体击中,它就会一直停留在那里。

但是一旦移动鼠标,光线投射就不会在移动的中间或到达距离时击中对象。

因此,当将鼠标移出对象区域时,它将开始向前移动到endPos或向后移动到startPos。

2 个答案:

答案 0 :(得分:1)

另一种方法:(不使用Raycast)

using UnityEngine;

public class Move : MonoBehaviour
{
    public float speed = 5f;
    public float distancetoMove = 1f;
    public bool goForward;
    public Vector3 startPos;
    public Vector3 endPos;

    private void Start()
    {
        startPos = transform.position;
        endPos = transform.position - Vector3.forward * distancetoMove;
    }

    void Update()
    {
        if (goForward)
        {
            transform.position = Vector3.MoveTowards(transform.position, endPos, speed * Time.deltaTime);
        }
        else
        {
            transform.position = Vector3.MoveTowards(transform.position, startPos, speed * Time.deltaTime);
        }
    }

    private void OnMouseOver()
    {
        goForward = true;
    }

    private void OnMouseExit()
    {
        goForward = false;
    }
}

如果要在if中使用ot,则必须声明Perc超出else 解决您的问题

更改:

if (hit.transform.tag == tag)

transform.position = Vector3.Lerp(start, endPos, Perc);

对此:     transform.position = Vector3.Lerp(transform.position, endPos, Perc);

else

else{
    transform.position = Vector3.Lerp(endPos, startPos, Perc);
}  

对此:

else{
        transform.position = Vector3.Lerp(transform.position, startPos, Perc);
    }

您的代码将如下所示:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OnMouseOverEvent : MonoBehaviour
{
    public float duration;
    public string tag;
    public Vector3 startPos;
    public Vector3 endPos;
    public float distancetoMove = 1f;
    public float lerpTime = 5;
    float Perc;

    private float currentLerpTime = 0;

    private void Start()
    {
        startPos = transform.position;
        endPos = transform.position - Vector3.forward * distancetoMove;
    }

    private void Update()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit, 100))
        {
            if (hit.transform.tag == tag)
            {
                currentLerpTime += Time.deltaTime;
                if (currentLerpTime >= lerpTime)
                {
                    currentLerpTime = lerpTime;
                }

                Perc = currentLerpTime / lerpTime;
                transform.position = Vector3.Lerp(transform.position, endPos, Perc);
            }
            else
            {
                transform.position = Vector3.Lerp(transform.position, startPos, Perc);
            }
        }
    }
}

答案 1 :(得分:0)

插值(Perc)更新不正确

您的对象当前在更新中移动{​​{1}},其内插值为Lerp
问题在于,仅当光线投射击中此对象时,才通过lerp计时器更新Perc的代码。

您可以在完成移动过程之前/之后通过lerp-timer更新Perc

Perc

注意:您可能会注意到private float Perc; private void Update() { GetPercByLerpTime(); // Update before it moves Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, 100)) { if (hit.transform.tag == tag) { transform.position = Vector3.Lerp(startPos, endPos, Perc); } else { transform.position = Vector3.Lerp(endPos, startPos, Perc); } } // Or you can update your 'Perc' here. } private void UpdatePercByLerpTime(){ currentLerpTime += Time.deltaTime; if(currentLerpTime >= lerpTime) { currentLerpTime = lerpTime; } Perc = currentLerpTime / lerpTime; } 会一直递增,直到达到currentLerpTime,并且它将保持与lerpTime相同的值。

您可能想要实现减少或重置lerpTime的功能。

如果射线投射什么也不会发生,就不会发生任何运动。

您当前的代码仅在射线投射击中物体时才移动对象。 (尽管它确实会朝正确的方向移动,具体取决于它是否碰到了该对象)

您可能想要的是,如果射线投射未击中 或击中其他物体,则将对象移回起始位置。

所以您的最终结果将如下所示:

currentLerpTime