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

Unity实现《羞辱》时间弯曲机制:仅玩家不受时间暂停影响

Unity实现《羞辱》风格时间弯曲机制(仅暂停非玩家对象)

直接放弃修改Time.timeScale的方案——它会全局影响所有依赖时间的系统,包括玩家的物理和动画。我们用单独控制非玩家对象时间更新的方式来实现,步骤如下:

1. 给非玩家对象添加时间控制脚本

创建一个名为TimeControlledObject.cs的脚本,挂到所有需要被暂停的非玩家对象上(比如敌人、可交互物体、粒子特效等,玩家对象绝对不能挂这个脚本):

using UnityEngine;

public class TimeControlledObject : MonoBehaviour
{
    // 全局暂停状态,供控制器脚本修改
    public static bool isTimePaused = false;

    private Rigidbody _rb;
    private Animator _anim;
    private ParticleSystem _ps;
    private Vector3 _savedVelocity;
    private Vector3 _savedAngularVelocity;
    private float _savedAnimSpeed;
    private float _savedParticleSpeed;

    void Awake()
    {
        // 获取组件,没有的话不处理
        _rb = GetComponent<Rigidbody>();
        _anim = GetComponent<Animator>();
        _ps = GetComponent<ParticleSystem>();

        if (_anim != null) _savedAnimSpeed = _anim.speed;
        if (_ps != null) _savedParticleSpeed = _ps.main.playbackSpeed;
    }

    void Update()
    {
        if (isTimePaused)
        {
            PauseObject();
        }
        else
        {
            ResumeObject();
        }
    }

    void PauseObject()
    {
        // 保存刚体当前速度,然后停止运动
        if (_rb != null)
        {
            _savedVelocity = _rb.velocity;
            _savedAngularVelocity = _rb.angularVelocity;
            _rb.velocity = Vector3.zero;
            _rb.angularVelocity = Vector3.zero;
            // 可选:冻结位置/旋转,防止碰撞干扰
            _rb.constraints = RigidbodyConstraints.FreezeAll;
        }

        // 暂停动画
        if (_anim != null) _anim.speed = 0f;

        // 暂停粒子系统
        if (_ps != null)
        {
            var mainModule = _ps.main;
            mainModule.playbackSpeed = 0f;
            _ps.Pause();
        }
    }

    void ResumeObject()
    {
        // 恢复刚体速度
        if (_rb != null)
        {
            _rb.constraints = RigidbodyConstraints.None;
            _rb.velocity = _savedVelocity;
            _rb.angularVelocity = _savedAngularVelocity;
        }

        // 恢复动画速度
        if (_anim != null) _anim.speed = _savedAnimSpeed;

        // 恢复粒子系统
        if (_ps != null)
        {
            var mainModule = _ps.main;
            mainModule.playbackSpeed = _savedParticleSpeed;
            _ps.Play();
        }
    }
}

2. 玩家输入控制器

创建TimeBendController.cs脚本,挂到玩家对象上,用来触发时间暂停/恢复:

using UnityEngine;

public class TimeBendController : MonoBehaviour
{
    // 设置触发按键,这里用左Shift,你可以改成自己需要的键
    public KeyCode timeBendKey = KeyCode.LeftShift;

    void Update()
    {
        // 按下按键时切换暂停状态
        if (Input.GetKeyDown(timeBendKey))
        {
            TimeControlledObject.isTimePaused = !TimeControlledObject.isTimePaused;
        }
    }
}

3. 新手注意事项

  • 不要给玩家对象挂TimeControlledObject:玩家的刚体、动画会完全不受影响,正常运行。
  • 场景中遗漏的对象:如果有某些非玩家对象没挂脚本,它们不会被暂停,记得检查所有需要暂停的物体(比如场景中的门、掉落的道具)。
  • 协程处理:如果非玩家对象用了协程,默认协程依赖Time.timeScale,要把协程里的时间判断改成用Time.unscaledDeltaTime或者Time.realtimeSinceStartup,比如:
    // 错误写法(依赖timeScale)
    yield return new WaitForSeconds(2f);
    // 正确写法(不受timeScale影响,适用于需要在暂停时继续运行的协程)
    yield return new WaitForSecondsRealtime(2f);
    
  • 物理碰撞:暂停后如果玩家和被冻结的刚体碰撞,不会有物理反馈(因为刚体被冻结了),如果需要保留碰撞效果,可以去掉_rb.constraints = RigidbodyConstraints.FreezeAll,只清空速度——但这样可能会有轻微的位置偏移,按需选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:00:20