You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

3D移动平台碰撞异常求助:玩家可穿过平台(附Unity代码)

问题分析与解决方案

你的核心问题在于直接修改平台的transform.position会绕过Unity物理引擎的碰撞处理,导致物理系统无法正确识别平台的运动状态,进而让玩家穿过平台。同时手动计算玩家位置的逻辑存在缺陷(比如用velocity.magnitude这种速度大小判断,而非X方向的速度分量),且缺少触发器的添加/移除逻辑来维护contacts列表。

修正方案

1. 改用Rigidbody控制平台移动

给平台添加Rigidbody组件,勾选Is Kinematic(平台由脚本控制,不需要物理模拟外力),然后用Rigidbody.MovePosition移动平台,让物理引擎正确处理碰撞和带动玩家。

2. 完善触发器的接触列表维护

补充OnTriggerEnter和OnTriggerExit方法,正确更新contacts列表,确保只有玩家接触平台时才处理跟随逻辑。

3. 统一用FixedUpdate处理物理逻辑

物理相关操作必须放在FixedUpdate中,保证不同帧率下运动速度一致。

修改后的完整代码

using UnityEngine;
using System.Collections.Generic;

public class OscilateX : MonoBehaviour
{
    private float startX;
    private float val;
    public float speed;
    public float distance;
    private Rigidbody rb;

    public List<GameObject> contacts = new List<GameObject>();

    void Start()
    {
        startX = transform.position.x;
        val = 0;
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        val += Time.fixedDeltaTime;
        // 计算平台目标位置
        float targetX = startX + Mathf.Sin(val * speed) * distance;
        Vector3 targetPos = new Vector3(targetX, transform.position.y, transform.position.z);
        
        // 用Rigidbody移动,物理引擎自动处理碰撞跟随
        rb.MovePosition(targetPos);
    }

    // 触发器检测:玩家进入平台范围时加入列表
    void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            if (!contacts.Contains(other.gameObject))
            {
                contacts.Add(other.gameObject);
            }
        }
    }

    // 触发器检测:玩家离开平台范围时移除列表
    void OnTriggerExit(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            contacts.Remove(other.gameObject);
        }
    }
}

额外说明

  • 玩家对象需要有Rigidbody组件(勾选Use Gravity)和正确的碰撞器,这样站在Kinematic平台上时,物理引擎会自动带动玩家跟随平台运动,无需手动修改玩家位置。
  • 如果仍需手动控制玩家速度(不推荐,优先依赖物理引擎),可在FixedUpdate中计算平台速度,叠加到玩家Rigidbody速度上:
// 在FixedUpdate的rb.MovePosition之后添加
Vector3 platformVelocity = (targetPos - rb.position) / Time.fixedDeltaTime;
foreach (GameObject player in contacts)
{
    Rigidbody playerRb = player.GetComponent<Rigidbody>();
    if (playerRb != null)
    {
        // 叠加平台X方向速度到玩家身上
        playerRb.velocity = new Vector3(platformVelocity.x, playerRb.velocity.y, playerRb.velocity.z);
    }
}

内容的提问来源于stack exchange,提问作者Veerdex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 05:53:30