实战中的问题
实战中的问题
一、人物为什么没有动画情况下是张开双臂的状态
答案:建模时要绑定骨骼,四肢要明确反映出来,具体到底是头躯干还是腿,默认使用T字模型。
二、速通新InputSystem
1.InputSystem是什么
绑定—》按下—》开始、触发、结束三个事件

2.Action参数

3.输入动作设置

4. 相互作用设置


5.值加工设置

6.按键绑定


7.InputAction类使用
(1)启用输入检测
委托变量.Enable();
(2)操作监听
三个基本事件

监听函数
使用
CallbackContext
获取信息
CallbackContext context
参数包含了触发动作的所有信息。你可以使用这个上下文来访问更多细节,例如:
context.ReadValue<float>()
: 获取输入值(例如,对于键盘按键或手柄按钮)。context.control
: 获取触发该动作的输入控件。context.interaction
: 获取当前交互类型(例如,是否为按下、释放等)。context.phase
: 获取当前事件阶段(例如,Started、Performed、Canceled等)。


8.InputSystem Packages设置

三.=>是什么意思
=>
是C# 6.0引入的表达式体成员语法,它允许将方法体简写为一个表达式。
1 | protected virtual void Awake() => CacheAction(); |
等价于
1 | protected virtual void Awake() |
四、?.用法
判断实例在不在,在才能执行(点出来)
1 | m_moveEvent?.Enable();//判断m_movezEvent在不在,在就执行 |
五、自引用泛型抽象类 Entity<T>
CRTP(Curiously Recurring Template Pattern)是一种利用模板继承实现 静态多态(Static Polymorphism) 的设计模式。通过基类模板以派生类作为模板参数,CRTP 允许在编译期实现多态行为,避免虚函数开销,同时提供灵活的类型操作。以下通过代码和底层原理全面解析其实现和应用。
1 | public abstract class Entity : MonoBehaviour |
自引用泛型约束
1
where T : Entity<T>
是关键,它强制要求:
T
必须是Entity<T>
的子类(或自身)。- 例如:
Human
类继承自Entity<Human>
,此时T
被约束为Human
。
设计目的:
- 类型安全:在基类中可以直接使用
T
类型,而无需强制类型转换。 - 自引用支持:允许在基类中实现需要返回子类类型的方法(如克隆、工厂模式)。
- 扩展性:为具体实体类提供类型安全的通用逻辑。
- 类型安全:在基类中可以直接使用
例子:
1 | public class Human : Entity<Human> |

六、通过反射动态创建泛型类型实例
1 | (EntityState<T>)System.Activator.CreateInstance(System.Type.GetType(typeName)); |
Type.GetType(typeName)
- 根据字符串
typeName
获取类型信息。 typeName
必须是完整的类型名称(包括命名空间),例如:- 非泛型类型:
"MyNamespace.MyClass"
- 泛型类型:
"MyNamespace.EntityState
1[[System.String, mscorlib]]”`(需转义)
- 非泛型类型:
- 根据字符串
Activator.CreateInstance(Type)
- 动态创建指定类型的实例。
- 如果类型不存在或无法实例化(如抽象类),会抛出
ArgumentNullException
、MissingMethodException
等异常。
- 强制转换
(EntityState<T>)
- 假设
typeName
对应的类型是EntityState<T>
或其派生类。 - 如果类型不兼容,会抛出
InvalidCastException
。
- 假设
疑惑:为什么要用反射动态创建泛型类型实例
答:泛型参数
T
在编译时未知,需根据运行时逻辑确定。这样可以避免每个T重复代码。
七、线性过度平滑
从死区外的范围重新映射到0到1之间,实现了在离开死区后的
线性平滑过渡
,从而避免输入值的突然跳跃。
- 数学映射过程 :(要映射的值-死区值)/(1-死区值)
输入值在死区内
(value ≤ deadzone
):- 计算结果为负数(如
value=0.1
,deadzone=0.2
→(0.1-0.2)/0.8 = -0.125
)。 实际使用时通常截断为0
,表示忽略死区内的微小输入。
- 计算结果为负数(如
输入值在死区外
(value > deadzone
):- 将原始输入范围
[deadzone, 1]
线性映射到[0, 1]
。 - 示例:
- 当
deadzone=0.2
,value=0.3
→(0.3-0.2)/0.8 = 0.125
。 value=1
→(1-0.2)/0.8 = 1
。
- 当
- 将原始输入范围
1 | axis.x = Mathf.Abs(axis.x) > deadzone ? RemapToDeadzone(axis.x,deadzone) : 0; |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 游戏开发笔记!
评论