如何让平台在一段时间后不与 Unity 中的玩家对象碰撞?

时间:2021-04-17 00:24:46

标签: c# unity3d

总的来说,我是 Unity 和 C# 的新手,所以请原谅我的术语(或缺少术语)...

我已经成功 - 在朋友的帮助下,应该归功于它 - 使平台在与玩家碰撞一帧后上升一定数量!唯一的问题是,现在,我似乎无法让它再次向下移动...... 这位朋友挑战我让它上升,在空中停留一段时间,然后再下降。

这是我的工作代码片段,可以让它上升。

bool HaveCollided = false; //Collision checker boolean

void Update()
    {
        Vector3 up = lifter * Time.deltaTime;
        if (HaveCollided != true || transform.position.y >= 5)
        {
            return;
        }
    }
void OnCollisionEnter(Collision collision) //Makes HaveCollided true at collision event
    {
        if (collision.gameObject.GetComponent<Playertag>() != null) //don't use GetComponent in Update()
        {
            HaveCollided = true;
        }

因此,如果我的逻辑是正确的,我需要在条件为:HaveCollided != true || transform.position.y >= 5 的语句中嵌套另一个 if 语句:

if (newTime == Time.deltaTime * CertainAmount && transform.position.y >= 1) //make platform go down until y position is equal to 1
        {
            //make platform go down
            Debug.Log("reached");
            transform.position = transform.position - up;
        }

但它不起作用。它甚至似乎还没有到达会使平台下降的部分。我真的不知道从哪里开始......

2 个答案:

答案 0 :(得分:0)

根据您的评论,我进行了一些修改,以使平台移动更顺畅。我也做了它,所以向上和向下运动都可以使用相同的功能。

using UnityEngine;
using System.Collections;

[SerializeField] private float timeToMovePlatform = 0.0f;       // time it takes the platform to get from 1 point to another
[SerializeField] private float timeToRestAtPeak = 0.0f;         // time that the platform rests at the top of its movement
[SerializeField] private float platformYOffset = 0.0f;          // offset the platform moves from its origin point to float upward


private Coroutine movingPlatform = null;                         // determines if the platform is currently moving or not

private void OnCollisionEnter(Collision col)
{
    // add a tag to your player object as checking a tag at runtime vs. a GetComponent is faster
    if(col.gameObject.tag == "Player")
    {
        // only trigger when we are not currently moving
        if(movingPlatform == null)
        {
            // start our coroutine so the platform can move
            movingPlatform = StartCoroutine(MovePlatform(true));
        }
    }
}

/// <summary>
/// Moves this object up or down depending on the parameter passed in
/// </summary>
/// <param name="moveUpward">Determines if this object is currently moving upward or not</param>
private IEnumerator MovePlatform(bool moveUpward)
{
    // store our start position 
    Vector3 startPos = transform.position;
    
    // build our goal position based on which direction we are moving
    Vector3 goalPos = new Vector3(startPos.x, startPos + (moveUpward ? platformYOffset : -platformYOffset), startPos.z);
    
    // set our current time
    float currentTime = 0.0f;
    
    while(currentTime <= timeToMovePlatform)
    {
        // lerp the position over the current time compared to our total duration 
        transform.position = Vector3.Lerp(startPos, goalPos, currentTime / timeToMovePlatform); 
        
        // update our timer
        currentTime += Time.deltaTime;
        
        // need to yield out of our coroutine so it does not get stuck here
        yield return null;
    }
    
    // just in case there are any floating point issues, set our position directly
    transform.position = goalPosition;
    
    // when we are moving upward, make sure to stop at the peak for the set duration
    if(moveUpwards)
    {
        yield return WaitForSeconds(timeToRestAtPeak); 
        
        // once we are done waiting, we need to move back downward
        StartCoroutine(MovePlatform(false));
    }
    else
    {
        // we finished moving downward, so set our coroutine reference to false
        // so the player can set the platform to move again
        movingPlatform = null;
    }
}

公平警告,我没有测试此代码,这更像是我针对您的情况采取的方向。在做任何事情之前,给你的播放器添加一个标签。如果您不确定什么是标签,请查看 docs。请务必为玩家提供标签 Player,以便代码按预期工作。

您会注意到前三个变量是序列化的,但是是私有的。通过这样做,它允许 Unity 在检查器中显示它们,但不允许其他脚本触摸它们。

要了解有关协程的更多信息,请查看 docs,对于 Lerps,我喜欢这个 blog post。如果这对您有用和/或您有任何问题,请告诉我。

答案 1 :(得分:0)

最好的办法是添加碰撞器并使用 isTrigger。播种时间,如果在该时间段内未触发,则引发事件。