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

Unity赛车游戏悬挂脚本Gizmos仅单条线显示问题求助

赛车游戏悬挂脚本Gizmos绘制辅助线异常问题

我为赛车游戏编写了一款悬挂脚本,希望通过Gizmos绘制辅助线,帮助正确设置弹簧长度和行程。预期效果是:

  • 从悬挂对象位置向下绘制长度为restLength的红色线条
  • 在其两侧分别绘制从同一高度起始、长度为minLength的黄色线条和长度为maxLength的白色线条

目前Debug.DrawLine能正常工作,但我希望在运行游戏前就看到这些线条,且修改输入变量时线条自动调整。实际编译后仅红色线条按预期显示,其余线条均不出现;注释红色线条后则无任何线条显示。

我的当前代码:

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

public class Suspension : MonoBehaviour
{
    private Rigidbody rb;

    [Header("Suspension")]
    [SerializeField] float restLength;
    [SerializeField] float springTravel;
    [SerializeField] float springStiffness;
    [SerializeField] float damperStiffness;

    private float minLength;
    private float maxLength;
    private float previousLength;
    private float springLength;
    private float springVelocity;
    private float springForce;
    private float damperForce;

    private Vector3 suspensionForce;

    [Header("Wheel")]
    [SerializeField] float wheelRadius;

    [Header ("Ground Information")]
    public bool touchingGround;
    public Vector3 groundNormal;
    void Awake()
    {
        rb = transform.root.GetComponent<Rigidbody>();

        minLength = restLength - springTravel;
        maxLength = restLength + springTravel;
    }

    void FixedUpdate()
    {
        Debug.DrawLine(transform.position, transform.position + (restLength * -this.transform.up), Color.red, 0.0f, false);
        Debug.DrawLine(transform.position + (0.1f * this.transform.forward), transform.position + (0.1f * this.transform.forward) + (minLength * -this.transform.up), Color.yellow, 0.0f, false);
        Debug.DrawLine(transform.position + (0.1f * -this.transform.forward), transform.position + (0.1f * -this.transform.forward) + (maxLength * -this.transform.up), Color.white, 0.0f, false);
        if(Physics.Raycast(transform.position, -transform.up, out RaycastHit hit, maxLength + wheelRadius))
        {
            touchingGround = true;
            groundNormal = hit.normal;

            previousLength = springLength;
            springLength = hit.distance - wheelRadius;
            springLength = Mathf.Clamp(springLength, minLength, maxLength);
            springVelocity = (previousLength - springLength) / Time.fixedDeltaTime;
            springForce = springStiffness * (restLength - springLength);
            damperForce = damperStiffness * springVelocity;

            suspensionForce = (springForce + damperForce) * transform.up;
            rb.AddForceAtPosition(suspensionForce, hit.point);
        }
        else
        {
            touchingGround = false;
        }
    }

    private void OnDrawGizmos() 
    {
        Gizmos.color = Color.red;
        Gizmos.DrawLine(transform.position, transform.position + (restLength * -this.transform.up));
        Gizmos.color = Color.yellow;
        Gizmos.DrawLine(transform.position + (0.1f * this.transform.forward), transform.position + (0.1f * this.transform.forward) + (minLength * -this.transform.up));
        Gizmos.color = Color.white;
        Gizmos.DrawLine(transform.position + (0.1f * -this.transform.forward), transform.position + (0.1f * -this.transform.forward) + (maxLength * -this.transform.up));
    }
}

问题原因

minLength和maxLength仅在Awake方法中赋值,而Awake只在游戏运行时执行。编辑模式下调用OnDrawGizmos时,这两个变量保持默认值0,导致黄色和白色线条长度为0,无法显示。

解决方案

在OnDrawGizmos方法中实时计算minLength和maxLength,确保编辑模式下也能获取正确的数值:

修改后的OnDrawGizmos方法:

private void OnDrawGizmos() 
{
    // 实时计算最小/最大长度,不依赖Awake的初始化
    float currentMinLength = restLength - springTravel;
    float currentMaxLength = restLength + springTravel;

    Gizmos.color = Color.red;
    Gizmos.DrawLine(transform.position, transform.position + (restLength * -this.transform.up));
    Gizmos.color = Color.yellow;
    Gizmos.DrawLine(transform.position + (0.1f * this.transform.forward), transform.position + (0.1f * this.transform.forward) + (currentMinLength * -this.transform.up));
    Gizmos.color = Color.white;
    Gizmos.DrawLine(transform.position + (0.1f * -this.transform.forward), transform.position + (0.1f * -this.transform.forward) + (currentMaxLength * -this.transform.up));
}

另外,为了保证运行时和编辑模式下的逻辑一致性,也可以将minLength和maxLength的计算逻辑抽成一个公共方法,在Awake和OnDrawGizmos中都调用:

private void UpdateSuspensionLimits()
{
    minLength = restLength - springTravel;
    maxLength = restLength + springTravel;
}

void Awake()
{
    rb = transform.root.GetComponent<Rigidbody>();
    UpdateSuspensionLimits();
}

private void OnDrawGizmos() 
{
    UpdateSuspensionLimits(); // 编辑模式下更新极限值

    Gizmos.color = Color.red;
    Gizmos.DrawLine(transform.position, transform.position + (restLength * -this.transform.up));
    Gizmos.color = Color.yellow;
    Gizmos.DrawLine(transform.position + (0.1f * this.transform.forward), transform.position + (0.1f * this.transform.forward) + (minLength * -this.transform.up));
    Gizmos.color = Color.white;
    Gizmos.DrawLine(transform.position + (0.1f * -this.transform.forward), transform.position + (0.1f * -this.transform.forward) + (maxLength * -this.transform.up));
}

这样修改后,编辑模式下调整restLength或springTravel时,Gizmos线条会实时更新,所有辅助线都能正常显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 02:20:05