游戏开发中渐进式属性目标值设置的通用实现方案咨询
渐进式属性调整的泛型封装方案
核心思路
用泛型类封装当前值、目标值、调整增量,内置统一的Update()方法处理渐进趋近逻辑,同时通过自定义插值委托适配不同数据类型(如数值、向量等),避免为每个字段重复编写冗余代码。
实现泛型类 InterpolatingProperty<T>
public class InterpolatingProperty<T> { // 当前属性值 public T Current { get; private set; } // 目标属性值 public T Target { get; private set; } // 插值逻辑委托:负责处理当前值向目标值的单次调整 private readonly Func<T, T, T, T> _interpolator; // 每次调整的增量/步长 private readonly T _increment; // 构造函数:传入初始值、增量、插值逻辑 public InterpolatingProperty(T initialValue, T increment, Func<T, T, T, T> interpolator) { Current = initialValue; Target = initialValue; _increment = increment; _interpolator = interpolator; } // 设置新的目标值 public void SetTarget(T target) { Target = target; } // 执行一次渐进调整 public void Update() { Current = _interpolator(Current, Target, _increment); } // 直接将当前值同步到目标值(跳过渐进过程) public void SnapToTarget() { Current = Target; } }
为不同类型编写插值逻辑
针对游戏中常见的数值、向量类型,编写对应的插值处理逻辑:
数值类型(以double为例)
// 处理double类型:每次向目标移动固定增量,到达目标后停止 public static double DoubleInterpolator(double current, double target, double increment) { if (current < target) { return Math.Min(current + increment, target); } else if (current > target) { return Math.Max(current - increment, target); } return current; }
二维向量类型(自定义Vector2示例)
public struct Vector2 { public double X { get; set; } public double Y { get; set; } public Vector2(double x, double y) { X = x; Y = y; } } // 处理Vector2类型:每个分量独立按增量趋近目标 public static Vector2 Vector2Interpolator(Vector2 current, Vector2 target, Vector2 increment) { return new Vector2( DoubleInterpolator(current.X, target.X, increment.X), DoubleInterpolator(current.Y, target.Y, increment.Y) ); }
在Camera类中使用泛型属性
public class Camera { // 封装缩放级别 private readonly InterpolatingProperty<double> _zoomLevel; // 封装相机世界位置 private readonly InterpolatingProperty<Vector2> _worldPosition; public Camera() { // 初始化缩放:初始值1.0,每次调整增量0.1 _zoomLevel = new InterpolatingProperty<double>(1.0, 0.1, DoubleInterpolator); // 初始化位置:初始(0,0),X/Y方向每次增量0.5 _worldPosition = new InterpolatingProperty<Vector2>( new Vector2(0, 0), new Vector2(0.5, 0.5), Vector2Interpolator ); } // 对外暴露设置缩放目标的方法 public void SetZoomTarget(double target) { _zoomLevel.SetTarget(target); } // 对外暴露设置位置目标的方法 public void SetPositionTarget(Vector2 target) { _worldPosition.SetTarget(target); } // 统一更新所有渐进式属性 public void Update() { _zoomLevel.Update(); _worldPosition.Update(); } // 对外提供当前缩放值的只读访问 public double CurrentZoom => _zoomLevel.Current; // 对外提供当前位置的只读访问 public Vector2 CurrentPosition => _worldPosition.Current; }
扩展优化建议
- 如果需要基于时间的平滑插值(如Lerp),可以替换插值逻辑为:
public static double LerpInterpolator(double current, double target, double deltaTime) { // 0.1为平滑系数,值越大趋近速度越快 return current + (target - current) * 0.1 * deltaTime; } - 可给
InterpolatingProperty<T>添加IsAtTarget属性,判断当前值是否已到达目标,避免无效更新。
内容的提问来源于stack exchange,提问作者Rich. T.
相关产品推荐
相关产品推荐

