【问题标题】:player won't stick on a moving platform玩家不会停留在移动的平台上
【发布时间】:2014-12-30 19:38:34
【问题描述】:

我为我的游戏创建了一些移动平台。有一个名为 PlatformPath1 的游戏对象,它的子对象定义了平台循环的开始和结束,然后显然是遵循路径的实际平台。平台移动完美,但正如预期的那样,玩家不会随着平台移动。如何让玩家随平台移动?

这是 PlatformPath1 的代码

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

public class FollowPath : MonoBehaviour
{
    public enum FollowType
    {
        MoveTowards,
        Lerp
    }

    public FollowType Type = FollowType.MoveTowards;
    public PathDefinition Path;
    public float Speed = 1;
    public float MaxDistanceToGoal = .1f;

    private IEnumerator<Transform> _currentPoint;

    public void Start()
    {
        if (Path == null)
        {
            Debug.LogError("Path cannot be null", gameObject);
            return;
        }

        _currentPoint = Path.GetPathEnumerator();
        _currentPoint.MoveNext();

        if (_currentPoint.Current == null)
            return;

        transform.position = _currentPoint.Current.position;
    }

    public void Update()
    {
        if (_currentPoint == null || _currentPoint.Current == null)
            return;

        if (Type == FollowType.MoveTowards)
            transform.position = Vector3.MoveTowards (transform.position, _currentPoint.Current.position, Time.deltaTime * Speed);
        else if (Type == FollowType.Lerp)
            transform.position = Vector3.Lerp(transform.position, _currentPoint.Current.position, Time.deltaTime * Speed);

        var distanceSquared = (transform.position - _currentPoint.Current.position).sqrMagnitude;
        if (distanceSquared < MaxDistanceToGoal * MaxDistanceToGoal)
            _currentPoint.MoveNext();
    }
}

这是平台的代码

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

public class PathDefinition : MonoBehaviour
{
    public Transform[] Points;

    public IEnumerator<Transform> GetPathEnumerator()
    {
        if(Points == null || Points.Length < 1)
            yield break;

        var direction = 1;
        var index = 0;
        while (true)
        {
            yield return Points[index];

            if (Points.Length == 1)
                continue;

            if (index <= 0)
                direction = 1;
            else if (index >= Points.Length - 1)
                direction = -1;

            index = index + direction;
        }
    }

    public void OnDrawGizmos()
    {
        if (Points == null || Points.Length < 2)
            return;

        for (var i = 1; i < Points.Length; i++) {
            Gizmos.DrawLine (Points [i - 1].position, Points [i].position);
        }
    }
}

【问题讨论】:

    标签: unity3d unity3d-2dtools


    【解决方案1】:

    您可以将播放器作为孩子添加到平台。这样,当平台移动时,玩家也会移动。
    在运动结束时(或在某些用户输入时),您可以中断育儿。以下是一些您可以尝试的代码。

    public GameObject platform; //The platform Game Object
    public GameObject player;   //The player Game Object
    
    //Call this to have the player parented to the platform.
    //So, say for example, you have a trigger that the player steps on 
    //to activate the platform, you can call this method then
    void AttachPlayerToPlatform () {
        player.transform.parent = platform.transform;
    }
    
    //Use this method alternatively, if you wish to specify which 
    //platform the player Game Object needs to attach to (more useful)
    void AttachPlayerToPlatform (GameObject platformToAttachTo) {
        player.transform.parent = platformToAttachTo.transform;
    }
    
    //Call this to detach the player from the platform
    //This can be used say at the end of the platform's movement
    void DetachPlayerFromPlatform () {
        player.transform.parent = null;
    }
    

    【讨论】:

    • 我对玩家如何脱离平台感到有些困惑。你说脚本应该在平台移动结束时运行,但它是一个持续循环,玩家应该能够随时跳下。
    • 啊。现在清楚多了。那你想做的就是这个。如果你有一个跳跃映射,那么你可以在玩家每次跳跃时调用“DetachPlayerFromPlatform”,每次玩家与平台碰撞时调用“AttachPlayerToPlatform”。或者,您可以在平台边缘设置一个触发器,该触发器将在 OnTriggerExit 事件中调用 Detach 方法
    • 当我放入育儿代码时,我收到一条错误消息,内容为“当前上下文中不存在名称‘平台’。” ' void OnTriggerEnter(Collider2D col){ if(col.gameObject.tag == "Player"){ Player.transform.parent = platform.transform; } }'
    • 编写该代码时的假设是“平台”变量是一个公共的全局游戏对象。如果您想像尝试那样使用它,请改用这种方式。 (注意 Trigger 的签名) //签名是 OnTriggerEnter2D (Collider2D) for a 2D Collider void OnTriggerEnter2D (Collider2D col) { if(col.gameObject.tag == "Player") //假设 Player 对象是一个全局声明的 GameObject,这会将 Player 游戏对象的父级分配为该脚本附加到的平台 Player.transform.parent = this.transform; } }
    • 现在我得到一个错误,上面写着“需要一个对象来访问非静态成员 'UnityEngine.Component.transform'。如果我没记错的话,我需要将 this.transform 设置为该位置使用 Vector3,但我不知道该怎么做
    【解决方案2】:

    如果您要站在现实世界中的移动平台上,您会随着平台移动的原因是平台与您的脚之间的摩擦力。如果平台被冰覆盖,如果平台在您在平台上开始运动,您可能无法随平台一起移动!

    现在我们可以在您的游戏物理中实现这一点。通常,当您不尝试走路时,您的摩擦可能只会将您的播放器减速到零速度。相反,您可以在撞击时检查地面对撞机,以查看它是否具有移动平台脚本,并获取平台的速度。然后将此速度用作运动计算的“零点”。

    【讨论】:

    • 对不起,我不太明白
    • 你的玩家移动是由刚体控制的,还是你直接设置他们的transform.position?
    • 玩家使用刚体
    【解决方案3】:

    我以为这会很困难,但实际上我发现制作一个看起来效果很好的解决方案真的很简单。

    我游戏中的角色有一个 Box Collider。它不是触发器,也不使用物理材料。它有一个刚体,质量为 1,阻力为 0,角阻力为 0.05,使用重力,不是运动学的,不插值,碰撞检测是离散的。它没有约束。对于横向移动,我使用 transform.Translate,对于跳跃,我使用 Rigidbody 的 AddForceForceMode.VelocityChange 作为最后一个参数。

    移动平台还有一个 Box Collider。我根据每帧调用Vector3.Lerp 的结果设置transform.position。我在移动平台上也有这个脚本:

    void OnCollisionEnter(Collision collision) {
        // Attach the object to this platform, but have them stay where they are in world space.
        collision.transform.SetParent(transform, true);
        Debug.Log("On platform.");
    }
    
    void OnCollisionExit(Collision collision) {
        // Detach the object from this platform, but have them stay where they are in world space.
        collision.transform.SetParent(transform.parent, true);
        Debug.Log("Off platform.");
    }
    

    仅此而已。真的,只是脚本中的两行代码声明我正在实现这两个方法,然后每个方法的实际实现都是一行。一开始的所有信息都是为​​了以防碰撞检测在你的项目中实际上没有起作用(我总是忘记规则是什么,什么不被视为碰撞和/或触发器。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多