Lerp 立即执行,而不是逐渐执行。

huangapple go评论72阅读模式
英文:

Lerp being performed instantly, rather than gradually

问题

我一直在Unity中开发一个项目,正在制作一个UFO牛绑架游戏。我一直在研究RaycastHit,并尝试将其与Vector.Lerp相结合,以便当UFO正好位于牛预制体正上方时,它应该逐渐将其吸走。我遇到的问题是,当我直接位于牛预制体正上方时,它会立即被吸走,而不是逐渐吸走。

这与我以前使用raycastHit.transform.position的新Vector 3时的行为完全相同。请查看下面的TractorBeam类:

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

public class TractorBeam : MonoBehaviour
{
    private bool tractorBeamEnabled = false;
    public GameObject tractorBeam;

    public void StopTractorBeam(bool death)
    {
        if (death)
        {
            Destroy(GameObject.FindWithTag("TractorBeam"));
        }
    }

    void Start()
    {

    }

    void Update()
    {
        // 牵引光束
        tractorBeam.GetComponent<Renderer>().enabled = false;
        if (Input.GetKey("space"))
        {
            tractorBeamEnabled = true;
            tractorBeam.GetComponent<Renderer>().enabled = true;
            RaycastHit raycastHit;
            if (Physics.Raycast(transform.position, Vector3.down, out raycastHit, Mathf.Infinity))
            {
                if (raycastHit.collider.tag != "Jet" && (raycastHit.collider.tag == "Cow1" || raycastHit.collider.tag == "Cow2"))
                {
                    Debug.Log("Cow abducted!");
                    float startTime = Time.time;
                    float speed = 1f;
                    Transform endPos = raycastHit.transform;
                    Transform startPos = gameObject.transform;
                    float journeyLength = Vector3.Distance(startPos.position, endPos.position);
                    float distCovered = (Time.time - startTime * speed);
                    float fractionOfJourney = distCovered / journeyLength;
                    raycastHit.collider.transform.position = Vector3.Lerp(startPos.position, endPos.position, fractionOfJourney);
                    FindObjectOfType<GameManager>().PointManager(1);
                }
            }
        }
    }
}

在查看了一堆文章之后,我一直在尝试计算fractionOfJourney,以便它是逐渐移动到UFO,以及更改float速度变量,但无论我做什么,它似乎都是瞬间完成的。以前我确实有一个版本,在那个版本中,我的UFO会立即lerp到牛的位置,然后在我按住空格键时追踪它,但后来我进行了更改,无法弄清楚当时的操作,但我相当确定那时离成功很近(但再次强调它仍然是瞬间移动,所以可能没有我想象的那么接近)。

我还是Unity的新手,非常喜欢学习它,如果我的代码很糟糕,请原谅我!非常感谢您的帮助和建议,感谢您的时间。

英文:

Ive been working on a project within Unity where im making a UFO cow abduction game. I have been researching Raycasthit and trying to combine this with a Vector.Lerp so that when the UFO is directly above a cow prefab it should gradually suck it up. The issue im experiencing is that when am directly over a cow prefab it gets sucked up instantly rather than gradually.

Lerp 立即执行,而不是逐渐执行。

This is the exact same behaviour as when i was using a new Vector 3 for the raycastHit.tranform.position. Please see my TractorBeam class below:

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

public class TractorBeam : MonoBehaviour
{
// Start is called before the first frame update
private bool tractorBeamEnabled = false;
public GameObject tractorBeam;


public void StopTractorBeam(bool death)
{
    if (death)
    {
        Destroy(GameObject.FindWithTag(&quot;TractorBeam&quot;));
    }
}
void Start()
{
    
}



// Update is called once per frame
void Update()
{
    // Tractor beam
    tractorBeam.GetComponent&lt;Renderer&gt;().enabled = false;
    if (Input.GetKey(&quot;space&quot;))
    {

        tractorBeamEnabled = true;
        tractorBeam.GetComponent&lt;Renderer&gt;().enabled = true;
        RaycastHit raycastHit;
        if (Physics.Raycast(transform.position, Vector3.down, out raycastHit, Mathf.Infinity))
            if (raycastHit.collider.tag != &quot;Jet&quot; &amp;&amp; raycastHit.collider.tag == &quot;Cow1&quot; || raycastHit.collider.tag == &quot;Cow2&quot;)
            {
                Debug.Log(&quot;Cow abducted!&quot;);
                float startTime = Time.time;
                float speed = 1f;
                Transform endPos = raycastHit.transform;
                Transform startPos = gameObject.transform;
                float journeyLength = Vector3.Distance(startPos.position, endPos.position);
                float distCovered = (Time.time - startTime * speed);
                float fractionOfJourney = distCovered / journeyLength;
                raycastHit.collider.transform.position = Vector3.Lerp(startPos.position, endPos.position, fractionOfJourney);
                
                //raycastHit.transform.position = new Vector3(raycastHit.transform.position.x, gameObject.transform.position.y - raycastHit.transform.position.y, raycastHit.transform.position.z);
                FindObjectOfType&lt;GameManager&gt;().PointManager(1);
            }


    }
}
}

After looking at a bunch of articles ive been trying to calculate the fractionOfJourney so that it is a gradual movement to the UFO, as well as changing the float speed variable but regardless of what i do it seems to just be instant. I did have it before where my UFO was instantly lerping to the cow, and then tracking it whilst i held space but i have since made changes and cant figure out what i was doing then - but im pretty sure that was close (but again it was still just moving instantly so probably not as close as i thought).

Im still new to unity and really enjoying learning it so forgive me if my code is awful! Any help or tips would be really appreciated and thank you for your time.

答案1

得分: 1

Vector3.Lerp 插值计算两个给定位置之间的中间值,根据给定的因子在 01 之间。

float distCovered = (Time.time - startTime * speed); 这段代码基本等同于 Time.time - Time.time * speed,因为 startTime = Time.timespeed = 1f,所以结果是 0

所以你总是立即返回 gameObject.transform.position

通常,如果你只想线性移动到所需位置,你可以使用 Vector3.MoveTowards,它会根据固定速度朝目标移动:

raycastHit.transform.position = Vector3.MoveTowards(raycastHit.transform.position, transform.position, speed * Time.deltaTime);

请注意乘以 Time.deltaTime,将你的速度从每帧速度转换为独立于帧速度的每秒速度。


你甚至可以将 Y 轴的移动与 XZ 轴的移动分开,以更快地将对象吸附到光束中心,而不是向上移动,以防止对象的对角线移动。

例如:

var step = speed * Time.deltaTime;
var hitPos = raycastHit.transform.position;
var targetPos = transform.position;
var targetPosXZ = targetPos;
targetPosXZ.y = hitPos.y;
var newPos = Vector3.MoveTowards(hitPos, targetPosXZ, step * 3);
newPos.y = Mathf.MoveTowards(hitPos.y, targetPos.y, step);

raycastHit.transform.position = newPos;

这将导致对象以比向上快 3 倍的速度移动到光束中心,你可以根据需要进行调整。


此外,你还可以检查:

if (raycastHit.transform.position == transform.position)
{
    Destroy(raycastHit.transform.gameObject);
    FindObjectOfType<GameManager>().PointManager(1);
}

你可能更愿意使用 Physics.SphereCast 来覆盖一定半径,而不仅仅是一个单独的射线,根据你的光束视觉效果。

英文:

Vector3.Lerp interpolates between the two given positions and a given factor between 0 and 1.

Your

float distCovered = (Time.time - startTime * speed);

basically equals

Time.time - Time.time * speed // since startTime = Time.time
Time.time - Time.time * 1 // since speed = 1f
= 0

=> You always instant return

gameObject.transform.position

In general if you just want to linear move towards the desired position you could use Vector3.MoveTowards instead which as said moves towards the target with a fixed velocity

raycastHit.transform.position = Vector3.MoveTowards(raycastHit.transform.position, transform.position, speed * Time.deltaTime);

Note the multiplication by Time.deltaTime which converts your value from a speed per frame into a frame rate independent speed per second.


You could even split the Y movement from the XZ movement in order to "suck" the object faster to the center of the beam than upwards - preventing a diagonal movement of the objects

Something like e.g.

var step = speed * Time.deltaTime;
var hitPos = raycastHit.transform.position;
var targetPos = transform.poaition;
var targetPosXZ = targetPos;
targetPosXZ.y = hitPos.y;
var newPos = Vector3.MoveTowards(hitPos, targetPosXZ, step * 3);
newPos.y = Mathf.MoveTowards(hitPos.y, targetPos.y, step);

raycastHit.transform.position = newPos;

Which would cause the object to move towards the beam center 3 times the velocity than upwards, which you can adjust accordingly.


Then further you could also include a check for

if(raycastHit.transform.position ==  transform.position)
{
    Destroy(raycastHit.transform.gameObject);
    FindObjectOfType&lt;GameManager&gt;().PointManager(1);
}

You might be interested in rather using a Physics.SphereCast instead in order to cover a certain radius and not only a single ray - according to your beam visuals

huangapple
  • 本文由 发表于 2023年2月24日 00:55:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75547933.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定