Unity3D 玩家停留在移动平台

我正在用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;

// 使用这个初始化
void Start () 
{
    origY = transform.position.y;
    useSpeed = -directionSpeed;
}

//每帧调用一次更新
void Update ()
{
    if(origY - transform.position.y > distance)
    {
        useSpeed = directionSpeed; //翻转方向
    }
    else if(origY - transform.position.y < -distance)
    {
        useSpeed = -directionSpeed; //翻转方向
    }
    transform.Translate(0,useSpeed*Time.deltaTime,0);
}
//AND here is the code for the Player's movement (in 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);

        //运行代码
        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);

EDIT: 我想可能和我如何定义玩家与平台有关,但是我尝试了不同的组合。如果平台是一个触发(在对撞机上),玩家一贯的穿过它。如果不是,我就不能用OnTrigger函数。玩家和平台都附有刚体,但是好像也没有影响到任何东西。当玩家在某些设置中的确在平台上,他只是战战兢兢的,以掉落结束。

原问题:Stay on Moving Platforms

阅读 7.1k
1 个回答

@Kay:
你需要的似乎是平台上的第二个对撞机。主对撞机有isTrigger = false来保证角色控制器有效工作。第二个运行isTrigger = true,它唯一的功能是检测玩家调用OnTriggerEnter时附在平台上,把平台留在OnTriggerExit。
由于你不能让两个对撞机都是一个类型(我猜你需要BOX对撞机),在平台游戏对象下建立空的子对象,并把BOX对撞机指定给它。我通常用一个叫做ActionMaterial的特殊物理材料让我的东西保持干净。如果你用的是层并且已经调整了碰撞矩阵,保证碰撞由physX控制。


@erosigma
这不是最好的方法,但是你可以从玩家到移动平台执行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);
    }
}
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进