使用Ursina Engine开发Python FPS游戏遇错误,求解决方法
错误修复方案
1. 核心错误:未正确实例化Ursina应用
代码中app = Ursina写法错误,Ursina是类,必须通过()实例化,否则游戏核心渲染上下文(包括render节点)不会创建,直接导致NameError: name 'render' is not defined。
修复代码:
app = Ursina() # 添加括号,实例化应用
2. Texture参数大小写错误
代码里Texture='M1911-RIGHT'和Texture='knife'用了大写开头的Texture,但Ursina的Entity参数是小写的texture,大写写法会被识别为自定义属性,导致Texture对象初始化异常,出现AttributeError: _cached_image警告。
修复代码:
self.hand_gun = Entity(parent=self.controller.camera_pivot, scale=0.1, position=Vec3(0.7, -1, 1.5), rotation=Vec3(0, 170, 0), model='gun', texture='M1911-RIGHT', visible=False) self.knife = Entity(parent=self.controller.camera_pivot, scale=0.4, position=Vec3(0.7, -1, 1.5), rotation=Vec3(0, 170, 0), model='knife', texture='knife', visible=False)
3. 子弹移动逻辑错误
Bullet类的update方法中,使用time.daylight计算移动距离是错误的——time.daylight是表示夏令时的布尔值(0或1),应使用time.dt(帧间隔时间)实现平滑的帧无关移动。
修复代码:
self.world_position += self.forward * self.speed * time.dt
4. 方法调用名称错误
Player类的__init__里调用了self.switch_weapons(),但方法定义是switch_weapon(单数),名称不匹配会导致初始化时抛出AttributeError,需修正调用名称:
修复代码:
self.switch_weapon() # 去掉末尾的s
5. 初始化顺序优化(可选,更规范)
Player类的初始化建议先调用父类__init__,再创建FirstPersonController,避免潜在上下文问题:
调整后的Player类__init__:
def __init__(self, **kwargs): super().__init__(**kwargs) # 先初始化父类Entity self.controller = FirstPersonController(**kwargs) self.parent = self.controller # 设置父节点 # 后续武器初始化代码...
完整修复后的代码
from ursina import * from ursina.prefabs.first_person_controller import * class Player(Entity): def __init__(self, **kwargs): super().__init__(**kwargs) self.controller = FirstPersonController(**kwargs) self.parent = self.controller self.hand_gun = Entity(parent=self.controller.camera_pivot, scale=0.1, position=Vec3(0.7, -1, 1.5), rotation=Vec3(0, 170, 0), model='gun', texture='M1911-RIGHT', visible=False) self.knife = Entity(parent=self.controller.camera_pivot, scale=0.4, position=Vec3(0.7, -1, 1.5), rotation=Vec3(0, 170, 0), model='knife', texture='knife', visible=False) self.weapons = [self.hand_gun, self.knife] self.current_weapon = 0 self.switch_weapon() def switch_weapon(self): for i, v in enumerate(self.weapons): v.visible = (i == self.current_weapon) def input(self, key): try: self.current_weapon = int(key) - 1 self.switch_weapon() except ValueError: pass if key == 'scroll up': self.current_weapon = (self.current_weapon + 1) % len(self.weapons) self.switch_weapon() if key == 'scroll down': self.current_weapon = (self.current_weapon - 1) % len(self.weapons) self.switch_weapon() if key == 'left_mouse_down' and self.current_weapon == 0: Bullet(model='sphere', color=color.black, scale=0.2, position=self.controller.camera_pivot.world_position, rotation=self.controller.camera_pivot.world_rotation) def update(self): self.controller.camera_pivot.y = 2 - held_keys['left control'] class Bullet(Entity): def __init__(self, speed=50, lifetime = 10, **kwargs): super().__init__(**kwargs) self.speed = speed self.lifetime = lifetime self.start = time.time() def update(self): ray = raycast(self.world_position, self.forward, distance=self.speed*time.dt) if not ray.hit and time.time() - self.start < self.lifetime: self.world_position += self.forward * self.speed * time.dt else: destroy(self) app = Ursina() ground = Entity(model='plane', scale=20, texture='white_cube', texture_scale='mesh') player = Player(position=(0,10,0)) app.run()
内容的提问来源于stack exchange,提问作者Yunwoo Chang
相关产品推荐
相关产品推荐

