unity面向组合开发二:EC的代码实践
一、ECCore
需要在Unity项目中使用插件:UniRx,通过UniRx代替Mono的Update,Mono下做轮询性能消耗会有点大。
EntityMono代码:
using System; using System.Collections.Generic; using EC; using UniRx; using UnityEngine; namespace ECCore { public abstract class EntityMono : MonoBehaviour { private readonly List<CapBase> caps = new(); private IDisposable updateSubscription; public CapBase AddCap<T>() where T : CapBase, new() { // 检查是否已经添加了相同类型的 CapBase 实例 if (caps.Exists(cap => cap is T)) { Debug.LogWarning($"{typeof(T).Name} 已经添加了!"); return null; } // 创建新的实例并添加到 caps 列表中 var c = (T)System.Activator.CreateInstance(typeof(T)); caps.Add(c); LogErrorByCap(c); return c; } public T GetCap<T>() where T : CapBase { return (T)caps.Find(cap => cap is T); } public void RemoveCap(CapBase cap) { caps.Remove(cap); } private void Awake() { OnInit(); updateSubscription?.Dispose(); updateSubscription = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(0.01f)) .Subscribe(_ => OnUpdate()); } private void OnDestroy() { updateSubscription?.Dispose(); OnClear(); } // entity生命周期 protected abstract void OnInit(); protected abstract void OnUpdate(); protected abstract void OnClear(); void OnCollisionEnter(Collision collision) { GetCap<OnColliderCapBase>()?.OnCollisionEnter(collision); } void OnCollisionStay(Collision collision) { GetCap<OnColliderCapBase>()?.OnCollisionStay(collision); } void OnCollisionExit(Collision collision) { GetCap<OnColliderCapBase>()?.OnCollisionExit(collision); } void OnTriggerEnter(Collider otherCollision) { GetCap<OnTriggerCapBase>()?.OnTriggerEnter(otherCollision); } void OnTriggerStay(Collider otherCollision) { GetCap<OnTriggerCapBase>()?.OnTriggerStay(otherCollision); } void OnTriggerExit(Collider otherCollision) { GetCap<OnTriggerCapBase>()?.OnTriggerExit(otherCollision); } private void LogErrorByCap(CapBase cap) { switch (cap) { case OnColliderCapBase onColliderCapBase: if (GetComponent<Collider>() == null) { Debug.LogError("碰撞能力实体没有添加Collider:"+ name); } break; case OnTriggerCapBase onTriggerCapBase: var colliderComponent = GetComponent<Collider>(); if (colliderComponent == null) Debug.LogError("触发能力实体没有添加Collider:"+ name); else { if(!colliderComponent.isTrigger) Debug.LogError("触发能力实体没有勾选isTrigger:"+ name); } break; } } } }
CapBase代码:
namespace ECCore { public abstract class CapBase { public abstract void InitData(EntityMono initEntity); public abstract void OnClear(); } }
二、OnColliderCapBase和OnTriggerCapBase 碰撞能力基类和触发能力基类
碰撞和触发需要依赖Mono下内部方法,所以给碰撞能力和触发能力抽象出基类方法。
OnColliderCapBase代码:
using ECCore; using UnityEngine; namespace EC { public abstract class OnColliderCapBase : CapBase { public abstract void OnCollisionEnter(Collision collision); public abstract void OnCollisionStay(Collision collision); public abstract void OnCollisionExit(Collision collision); } }
OnTriggerCapBase代码:
using ECCore; using UnityEngine; namespace EC { public abstract class OnTriggerCapBase : CapBase { public abstract void OnTriggerEnter(Collider otherCollision); public abstract void OnTriggerStay(Collider otherCollision); public abstract void OnTriggerExit(Collider otherCollision); } }
三、GameEC
PlayerEntity代码:
using ECCore; using UnityEngine; namespace EC { public class PlayerEntity : EntityMono { public float mouseSensitivity = 10.0f; protected override void OnInit() { // AddCap<InputCap>().InitData(this); AddCap<MoveCap>().InitData(this); AddCap<GravityCap>().InitData(this); GetCap<GravityCap>()?.SetGravity(10); AddCap<LookCap>().InitData(this); AddCap<PlayerOnColliderCap>().InitData(this); } protected override void OnUpdate() { // 输入先这么做 不知道要不要加Cap 思考中..... Vector3 movement = Vector3.zero; Vector2 look = Vector2.zero; movement.x = Input.GetAxis("Horizontal"); movement.z = Input.GetAxis("Vertical"); look.x = Input.GetAxis("Mouse X"); look.y = Input.GetAxis("Mouse Y"); GetCap<LookCap>()?.Look(look, mouseSensitivity); GetCap<MoveCap>()?.Move(movement); } protected override void OnClear() { } } }
MoveCap代码:
using UnityEngine; using ECCore; namespace EC { public class MoveCap : CapBase { private EntityMono entity; public override void InitData(EntityMono initEntity) { entity = initEntity; } public void Move(Vector3 pos) { pos = entity.transform.TransformDirection(pos); entity.transform.position += pos; } public override void OnClear() { entity = null; } } }

浙公网安备 33010602011771号