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

Ursina Engine第一人称控制器重力及跳跃优化问题咨询

Ursina FirstPersonController 重力与穿地面问题优化方案

核心原因分析

穿地面问题本质是高速下落时的碰撞穿透(Tunneling),结合mesh碰撞体本身的精度/性能特性,以及默认控制器的重力逻辑设计,共同导致了偶尔穿透的现象。以下是针对性优化方案:


1. 限制下落速度+优化重力逻辑

默认FirstPersonController的重力是持续累加的,下落速度会越来越快,极易触发穿透。通过限制最大下落速度,同时平滑重力施加逻辑解决:

from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController

class CustomFPController(FirstPersonController):
    def __init__(self, **kwargs):
        self.max_fall_speed = 18  # 按需调整,避免速度过高
        super().__init__(**kwargs)

    def update(self):
        if not self.grounded:
            # 限制下落速度,避免瞬间位移过大
            self.y -= min(self.gravity * time.dt, self.max_fall_speed * time.dt)
        super().update()

# 使用自定义控制器
player = CustomFPController()

2. 替换碰撞体类型

mesh碰撞体精度高但不适合动态角色,优先用**胶囊碰撞体(CapsuleCollider)**替代,它是为角色设计的碰撞形状,性能和防穿透表现更优:

# 替换默认碰撞体为胶囊体(适配第一人称角色尺寸)
player.collider = CapsuleCollider(radius=0.35, height=1.7)

若必须保留mesh碰撞体,需启用凸包属性(仅适合简单形状):

player.collider = 'mesh convex'

3. 强化落地检测精度

默认的grounded判定可能存在延迟,改用射线检测精准判断是否接触地面,同时避免空中误触发跳跃导致的位置偏移:

class CustomFPController(FirstPersonController):
    def update(self):
        # 从角色脚下稍高处发射短射线,检测落地状态
        ground_ray = raycast(self.position + Vec3(0, 0.15, 0), Vec3(0, -1, 0), distance=0.25)
        self.grounded = ground_ray.hit
        super().update()

4. 启用连续碰撞检测(CCD)

利用Panda3D的CCD机制,针对高速移动的玩家强制检测路径上的碰撞,彻底解决穿透:

# 给玩家实体启用CCD
player.node().setCcdMotionThreshold(0.01)  # 移动超过该距离时触发CCD
player.node().setCcdSweptSphereRadius(0.35)  # 对应胶囊碰撞体的半径

优先级建议

优先尝试替换胶囊碰撞体+限制下落速度,这两个改动成本低且能解决绝大多数穿地面问题;若仍有残留,再逐步叠加射线检测和CCD优化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:25:25