Unity3d+Gameframework:entity实体代码分析,基于StarForce
游戏场景中,动态创建的一切物体定义为实体。此模块提供管理实体和实体组的功能,如显示隐藏实体、挂接实体(如挂接武器、坐骑,或者抓起另一个实体)等。实体使用结束后可以不立刻销毁,从而等待下一次重新使用。
EntityGroup
内部包含对象池
实体加载成功订阅
GameEntry.Event.Subscribe(ShowEntitySuccessEventArgs.EventId, OnShowEntitySuccess); protected virtual void OnShowEntitySuccess(object sender, GameEventArgs e) { ShowEntitySuccessEventArgs ne = (ShowEntitySuccessEventArgs)e; if (ne.EntityLogicType == typeof(MyAircraft)) { m_MyAircraft = (MyAircraft)ne.Entity.Logic; } }
EntityManager
GameFramework.Entity.EntityManager.Update
实体组轮询,变为单一实体OnUpdate
创建实体
StarForce.GameBase.Initialize
与加载UI类似
GameFramework.Entity.EntityManager.ShowEntity
GameFramework.Entity.EntityManager.ShowEntity EntityInstanceObject entityInstanceObject = entityGroup.SpawnEntityInstanceObject(entityAssetName); if (entityInstanceObject == null) { int serialId = ++m_Serial; m_EntitiesBeingLoaded.Add(entityId, serialId); m_ResourceManager.LoadAsset(entityAssetName, priority, m_LoadAssetCallbacks, ShowEntityInfo.Create(serialId, entityId, entityGroup, userData)); return; } InternalShowEntity(entityId, entityAssetName, entityGroup, entityInstanceObject.Target, false, 0f, userData);
如果实体组中对象池能实例出来,即立即返回
否则调用资源加载
实体资源表中确定ID与asset的关系
IDataTable<DREntity> dtEntity = GameEntry.DataTable.GetDataTable<DREntity>(); DREntity drEntity = dtEntity.GetDataRow(data.TypeId);
正在加载中实体释放
public void HideEntity(int entityId, object userData) { if (IsLoadingEntity(entityId)) { GameFrameworkLog.Info("实体{0}正在加载等待释放", entityId); m_EntitiesToReleaseOnLoad.Add(m_EntitiesBeingLoaded[entityId]); m_EntitiesBeingLoaded.Remove(entityId); return; }
Entity
实体接口,包含被挂载,或者挂载别的方法
根据资源加载出的GameObject–》挂载Entity脚本(继承了于MonoBehaviour)
/// <summary> /// 创建实体。 /// </summary> /// <param name="entityInstance">实体实例。</param> /// <param name="entityGroup">实体所属的实体组。</param> /// <param name="userData">用户自定义数据。</param> /// <returns>实体。</returns> public override IEntity CreateEntity(object entityInstance, IEntityGroup entityGroup, object userData) { GameObject gameObject = entityInstance as GameObject; Transform transform = gameObject.transform; transform.SetParent(((MonoBehaviour)entityGroup.Helper).transform); return gameObject.GetOrAddComponent<Entity>(); }
实体统一设置到实体组子物体下,那么武器跟随人动如何实现
namespace UnityGameFramework.Runtime { public sealed class Entity : MonoBehaviour, IEntity { private int m_Id; private string m_EntityAssetName; private IEntityGroup m_EntityGroup; private EntityLogic m_EntityLogic;
ObjecBase
对象基类
UI面板,资源(asset,resource),实体都是继承对象基类
EntityInstanceObject
实体实例对象,不会继承自MonoBehavior,在实体资源加载成功后调用创建
GameFramework.Entity.EntityManager.LoadAssetSuccessCallback
//实例化出来 EntityInstanceObject entityInstanceObject = EntityInstanceObject.Create(entityAssetName, entityAsset, m_EntityHelper.InstantiateEntity(entityAsset), m_EntityHelper); showEntityInfo.EntityGroup.RegisterEntityInstanceObject(entityInstanceObject, true); InternalShowEntity(showEntityInfo.EntityId, entityAssetName, showEntityInfo.EntityGroup, entityInstanceObject.Target, true, duration, showEntityInfo.UserData); ReferencePool.Release(showEntityInfo);
把预制体加载完成,然后实例化后GameObject设置为实体的Target
EntityLogic
public abstract class EntityLogic : MonoBehaviour
实体逻辑基类
实体挂载好Entity,后Entity初始化时挂载逻辑处理脚本
public abstract class Entity : EntityLogic,此实体与gf实体不是同样东西(不在同个命名空间中)
创建时,通过逻辑类型就传递下去
public static void ShowMyAircraft(this EntityComponent entityComponent, MyAircraftData data) { entityComponent.ShowEntity(typeof(MyAircraft), "Aircraft", Constant.AssetPriority.MyAircraftAsset, data); }
SurvivalGame
继承GameBase
游戏模式
Update中随机产生陨石实体
GameEntry.Entity.ShowAsteroid
TargetableObject
所有的实体逻辑继承
OnTriggerEnter,碰撞检测
放入到回收池,什么时候彻底去除引用
Weapon
增加武器实体,为什么能挂载人身上
武器挂载
在创建完成后,挂载在主角身上
StarForce.Weapon.OnShow
protected override void OnShow(object userData) { base.OnShow(userData); m_WeaponData = userData as WeaponData; GameEntry.Entity.AttachEntity(Entity, m_WeaponData.OwnerId, AttachPoint); }
AttachEntity
附加子实体GameFramework.Entity.EntityManager.AttachEntity
IEntity childEntity = childEntityInfo.Entity; IEntity parentEntity = parentEntityInfo.Entity; DetachEntity(childEntity.Id, userData); childEntityInfo.ParentEntity = parentEntity; parentEntityInfo.AddChildEntity(childEntity); parentEntity.OnAttached(childEntity, userData); childEntity.OnAttachTo(parentEntity, userData);
在childEntity.OnAttachTo(parentEntity, userData);设置unity 父子物体关系
protected internal virtual void OnAttachTo(EntityLogic parentEntity, Transform parentTransform, object userData) { CachedTransform.SetParent(parentTransform); }
InternalHideEntity隐藏实体
//先隐藏子实体 while (entityInfo.ChildEntityCount > 0) { IEntity childEntity = entityInfo.GetChildEntity(); HideEntity(childEntity.Id, userData); } //把自己从父实体上移除 IEntity entity = entityInfo.Entity; DetachEntity(entity.Id, userData); entityInfo.Status = EntityStatus.WillHide; entity.OnHide(m_IsShutdown, userData); entityInfo.Status = EntityStatus.Hidden; //实体组移除 EntityGroup entityGroup = (EntityGroup)entity.EntityGroup; entityGroup.RemoveEntity(entity); //放入到回收队列 m_RecycleQueue.Enqueue(entityInfo);
GameFramework.Entity.EntityManager.Update 中轮询处理实体进入实体组的对象池
//处理回收队列的实体 while (m_RecycleQueue.Count > 0) { EntityInfo entityInfo = m_RecycleQueue.Dequeue(); IEntity entity = entityInfo.Entity; EntityGroup entityGroup = (EntityGroup)entity.EntityGroup; entityInfo.Status = EntityStatus.WillRecycle; entity.OnRecycle(); entityInfo.Status = EntityStatus.Recycled; entityGroup.UnspawnEntity(entity); //实体组回收,相当于对象池 ReferencePool.Release(entityInfo); }
posted on 2022-09-07 22:50 luoyikun 阅读(110) 评论(0) 编辑 收藏 举报 来源
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
2021-09-07 unity3d:向量计算,AOE图形相交
2018-09-07 unity3d:ugui 每个字间隔间距