保持在移动平台上

6
我正在Unity中编写一个2D平台游戏,我想让玩家停留在移动平台上。我已经搜索和尝试了一两天,但没有什么进展。 基本上,我被告知要尝试保持角色与平台接触时一起移动。 首先,如果我使用任何与OnTriggerEnter()相关的内容,玩家将穿过平台。如果我使用OnCollisionEnter()(玩家有CharacterController,平台有BoxCollider),则根本没有反应。这是我发现的建议最多的两个方法。另一个方法是将玩家与平台进行父子关联,但这显然会引起“问题”(频繁提到,但从未解释)。 那么,我该如何让玩家停留在移动平台上?这是移动平台的代码:
public class MovingPlatform : MonoBehaviour
{
private float useSpeed;
public float directionSpeed = 9.0f;
float origY;
public float distance = 10.0f;

// Use this for initialization
void Start () 
{
    origY = transform.position.y;
    useSpeed = -directionSpeed;
}

// Update is called once per frame
void Update ()
{
    if(origY - transform.position.y > distance)
    {
        useSpeed = directionSpeed; //flip direction
    }
    else if(origY - transform.position.y < -distance)
    {
        useSpeed = -directionSpeed; //flip direction
    }
    transform.Translate(0,useSpeed*Time.deltaTime,0);
}

以下是玩家移动的代码(在Update中):

CharacterController controller = GetComponent<CharacterController>();
    float rotation = Input.GetAxis("Horizontal");
    if(controller.isGrounded)
    {
        moveDirection.Set(rotation, 0, 0); //moveDirection = new Vector3(rotation, 0, 0);
        moveDirection = transform.TransformDirection(moveDirection);

        //running code
        if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) //check if shift is held
        { running = true; }
        else
        { running = false; }

        moveDirection *= running ? runningSpeed : walkingSpeed; //set speed

        //jump code
        if(Input.GetButtonDown("Jump"))
        {
            //moveDirection.y = jumpHeight;
            jump ();
        }
    }
    moveDirection.y -= gravity * Time.deltaTime;
    controller.Move(moveDirection * Time.deltaTime);

编辑:我认为这可能与我定义的玩家和平台有关,但我尝试了不同的组合。如果平台是一个触发器(在其碰撞器上),玩家会一直穿过它。如果不是,则无法使用OnTrigger函数。我在玩家和平台上都附加了刚体,但似乎没有影响任何东西。在某些设置中,当玩家确实上了平台时,他会抖动并经常掉落。


我从未使用过Unity3D,但是当角色在平台上时,是否可以像moveDirection += theplatform.moveDirection这样做呢? - mbeckish
我已经尝试过了,但是在OnTrigger和OnCollision函数方面遇到了问题,这些函数应该负责“当玩家在平台上时”的部分。我认为这与我如何定义我的对象有关,但我不确定正确的定义方式是什么,以便使其正常工作。 - muttley91
此外,您需要确保角色的moveDirection.y永远不会小于平台的moveDirection.y,否则您将会掉落(除非Unity3D框架自动处理?) - mbeckish
不幸的是,Unity似乎无法自行完成此操作,因此我正在努力解决这个问题。除了已经提供的两种解决方案,我还将采纳您的建议,希望其中之一能够奏效! - muttley91
5个回答

2
您需要的似乎是在平台上添加第二个碰撞体。主要的碰撞体应该设置为isTrigger = false,以确保您的角色控制器正常工作。第二个碰撞体应该设置为isTrigger = true,其唯一的功能是在调用OnTriggerEnter时检测玩家是否与平台相连,并在OnTriggerExit时离开平台。
由于您不能拥有两个相同类型的碰撞体(我猜您需要盒形碰撞体),因此在平台游戏对象下建立一个空的子对象,并将盒形碰撞体分配给它。我通常使用一个名为ActionMaterial的特殊物理材料,以便使我的东西更加整洁。如果您正在使用层并已调整了碰撞矩阵,请确保PhysX处理您的碰撞。

我能否在同一对象上使用两个不同的碰撞器(一个盒子,一个胶囊)来达到相同的效果,而不是需要两个对象并且它们都需要移动脚本? 此外,我没有使用层,并且没有调整过碰撞矩阵。 - muttley91
允许使用不同的碰撞器。但要注意胶囊碰撞器成本更高。因此,如果有一个立方体形状,最好使用子对象解决方案。无需层,无需碰撞矩阵操作=>没有增加的复杂性 ;) 只有在遇到性能问题时才需要这些东西。我正在开发iOS应用,因此性能对我来说始终是一个问题。 - Kay
好的,明白了!所以你的意思是在场景中有两个游戏对象?你具体怎么把一个对象设置为另一个对象的子对象呢? - muttley91
我仍在使用这个解决方案。子平台需要使用OnTriggerEnter和OnTriggerExit函数,我该如何编写它们? - muttley91
也许https://dev59.com/tmYq5IYBdhLWcg3woCC7#14387936或其他一些关于碰撞器的答案可以帮助。 - Kay
显示剩余2条评论

1
这不是最好的方法,但你可以从玩家到移动平台执行一次RayCast。如果RayCast击中“MovingPlatform”,则可以检查Y轴上的差异以确定玩家是否足够接近它被视为“OnThePlatform”。然后,你只需像通常一样调整玩家的位置即可。
例如:
private bool isOnMovingPlatform;
private float offsetToKeepPlayerAbovePlatform = 2.2f;
private float min = 0.2f;
private float max = 1.2f;

private void Update()
{
RaycastHit hit;
if(Physics.Raycast (player.position, player.TransformDirection(Vector3.down), out hit))
{
    if(hit.transform.name.Contains("MovingPlatform"))
    {
        Transform movingPlatform  = hit.collider.transform;

        if(movingPlatform.position.y - player.position.y <= min && movingPlatform.position.y - player.position.y >= max)
        {
            isOnMovingPlatform = true;
        }
        else
        {
            isOnMovingPlatform = false;
        }
    }

    if(isOnMovingPlatform)
    {
        player.position = new Vector3(hit.transform.x, hit.transform.y + offsetToKeepPlayerAbovePlatform, 0);
    }
}
}

只是好奇,因为我即将尝试这个,最小值、最大值和偏移量,它们与平台的大小有关吗? - muttley91
不一定。最小值和最大值只是范围,以便您知道玩家与平台的相关位置。例如,如果玩家的Y值比最大值高5,那么很明显他不在平台上,反之亦然。更改这些范围,直到您获得一组好的浮点数。理论上,它们可以从平台的高度导出,但并非必须如此。 - Nestor Ledon

0

您应该添加链接中的相关信息,以便答案即使链接失效仍然有用和相关。 - drneel

0

确实很不错。但是你应该将其发布为评论或提供更多信息。只包含链接的答案将在SO上被删除(我刚刚失去了一些)。 - Kay

0

你也可以将玩家游戏对象的变换父级设置为平台的变换。这样可以让玩家在上面移动而不会停止。至于检测,射线投射虽然有点慢但能胜任。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接