总的来说,我是 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;
}
但它不起作用。它甚至似乎还没有到达会使平台下降的部分。我真的不知道从哪里开始......
答案 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。播种时间,如果在该时间段内未触发,则引发事件。