using UnityEngine; using Articy.Touhou; using Articy.Touhou.Features; public enum EEntityType { None, Master, MasterSoul, Monster, Door, Npc, Bullet, Pt, BlessInteract, } namespace Game { public delegate void EntityCreateHandler(GameEntity entity); public abstract partial class Util { private static bool CreateEntityCheck(string cfgId) { if (string.IsNullOrEmpty(cfgId)) { Util.Print("创建实体失败,cfgId为空"); return false; } var cfg = Util.GetConfig(cfgId); if (cfg is null) { Util.Print("创建实体失败,cfgId错误:", cfgId); return false; } if (!(cfg is IObjectWithFeatureEntityParam)) { Util.Print("创建实体失败,没有实体Feature:", cfgId); return false; } return true; } //创建子实体 public static void CreateSubEntity(int index, int ownerId, int targetId, Vector3 direction, Vector3 pos) { var owner = Util.GetEntity(ownerId); var cfgId = owner.CfgId(); if (!CreateEntityCheck(cfgId)) { return; } var cfg = Util.GetConfig(cfgId); var battleCfg = ((IObjectWithFeatureEntityParamBattle)cfg).GetFeatureEntityParamBattle(); var subEntityList = battleCfg.SubEntityList; if (subEntityList.Count == 0) { Util.Print("子实体数量为0:", cfgId); return; } if (index < 0 || index >= subEntityList.Count) { Util.Print("子实体创建失败 序号错误:", cfgId, index, subEntityList.Count); return; } var subCfgId = subEntityList[index].TechnicalName; var team = owner.Team(); CreateEntity(subCfgId, (entity) => { entity.SetTeam(team); entity.SetOwner(ownerId); entity.SetTarget(targetId); Util.SetEntityPos(entity, pos); if (entity.hasBullet) { entity.bullet.CastDir = direction; Util.CastSkillBullet(entity); } }); } public static void CreateEntityImmediately(string cfgId, EntityCreateHandler callback) { if (!CreateEntityCheck(cfgId)) { return; } var entity = Contexts.sharedInstance.game.CreateEntity(); entity.AddID(cfgId, null); entity.iD.Data.IsCreate = false; CreateEntityReal(entity); callback(entity); } public static void CreateEntity(string cfgId, EntityCreateHandler callback) { if (!CreateEntityCheck(cfgId)) { return; } var entity = Contexts.sharedInstance.game.CreateEntity(); entity.AddID(cfgId, callback); } public static void CreateEntityReal(GameEntity entity) { var cfgId = entity.CfgId(); var cfg = Util.GetConfig(cfgId); var basicCfg = ((IObjectWithFeatureEntityParam)cfg).GetFeatureEntityParam(); var entityType = (EEntityType)basicCfg.EntityType; switch (entityType) { case EEntityType.Master: UtilEntityPackage.CreateMaster(entity); break; case EEntityType.MasterSoul: UtilEntityPackage.CreateMasterSoul(entity); break; case EEntityType.Monster: UtilEntityPackage.CreateMonster(entity); break; case EEntityType.Door: UtilEntityPackage.CreateDoor(entity); break; case EEntityType.Npc: UtilEntityPackage.CreateNpc(entity); break; case EEntityType.BlessInteract: UtilEntityPackage.CreateBlessInteract(entity); break; case EEntityType.Bullet: UtilEntityPackage.CreateBullet(entity); break; case EEntityType.Pt: UtilEntityPackage.CreatePoint(entity); break; } BuildBasic(entity, basicCfg); if (cfg is IObjectWithFeatureEntityParamBattle battle) { var battleCfg = battle.GetFeatureEntityParamBattle(); BuildBattle(entity, battleCfg); } if (cfg is IObjectWithFeatureEntityParamView view) { var viewCfg = view.GetFeatureEntityParamView(); BuildView(entity, viewCfg); } if (cfg is IObjectWithFeatureBlessInteractParam param) { var blessInteractCfg = param.GetFeatureBlessInteractParam(); BuildBlessInteract(entity, blessInteractCfg); } if (cfg is IObjectWithFeatureBullet bullet) { var bulletCfg = bullet.GetFeatureBullet(); BuildBullet(entity, bulletCfg); } if (cfg is IObjectWithFeatureEntityParamMonster monster) { var monsterCfg = monster.GetFeatureEntityParamMonster(); BuildMonster(entity, monsterCfg); } } private static void BuildBasic(GameEntity entity, EntityParamFeature basicCfg) { var view = entity.view; var offsetY = basicCfg.ViewOffset / 64f; view.TransformViewOffset.localPosition = new Vector3(0, offsetY, 0); view.TransformViewOther.localPosition = new Vector3(0, offsetY, 0); view.TransformViewMain.localPosition = Vector3.zero; var id = entity.iD; id.Data.BasicCfg = basicCfg; //加载动画 if (!entity.hasAnimation || string.IsNullOrEmpty(basicCfg.AnimationName)) { return; } var animation = entity.animation; foreach (var item in GameConst.AllAnimationState) { var basicName = $"basic_{item}"; var name = basicCfg.AnimationName; var nameSplit = name.Split('/'); var characterName = nameSplit[nameSplit.Length - 1]; var clipName = $"Character/{name}/{characterName}_{item}"; var clip = ResourceManager.Instance.Load(clipName); if (!(clip is null)) { animation.AnimatorOverrideController[basicName] = clip; } } } private static void BuildBattle(GameEntity entity, EntityParamBattleFeature cfg) { var moveParamCfg = cfg.MoveParam; var shieldParamCfg = cfg.ShieldParam; var stunParamCfg = cfg.StunParam; //移动 if (entity.hasMove) { var moveParam = entity.move.MoveParam; var basicParam = ((IObjectWithFeatureMoveParamBasic)moveParamCfg).GetFeatureMoveParamBasic(); var jumpParam = ((IObjectWithFeatureMoveParamJump)moveParamCfg).GetFeatureMoveParamJump(); moveParam.MoveForce = basicParam.MoveForce; moveParam.MoveSpeedMax = basicParam.SpeedMax; moveParam.AirDrag = basicParam.AirDrag; moveParam.GroundDrag = basicParam.GroundDrag; moveParam.Gravity = basicParam.Gravity; moveParam.NeedScale = basicParam.needScale; moveParam.JumpTimeMax = jumpParam.JumpTimeMax; moveParam.JumpTimeMin = jumpParam.JumpTimeMin; moveParam.JumpForce = jumpParam.JumpForce; moveParam.FallForce = jumpParam.fallSpeed; moveParam.AirSpeedMaxRate = jumpParam.airMoveRate; } //血量 护盾 处决条 眩晕条 if (entity.hasHp) { //血量 var hp = entity.hp; hp.HpMax.Value = cfg.HpMax; hp.Hp.Value = cfg.HpMax; //护盾 hp.ShieldMax.Value = cfg.ShieldMax; hp.Shield.Value = cfg.ShieldMax; //护盾参数 if (!(shieldParamCfg is null)) { var shieldParam = ((IObjectWithFeatureShield)shieldParamCfg).GetFeatureShield(); hp.ShieldRecoverTimeMax = shieldParam.Time; hp.ShieldRecoverTime = shieldParam.Time; hp.ShieldRecover = shieldParam.RecoverSpeed; if (entity.hasProperty) { Util.SetProperty(entity, EProperty.ShieldStaggerDefLevel, (int)shieldParam.StaggerDefLevel); } } //眩晕参数 if (!(stunParamCfg is null)) { var stunParam = ((IObjectWithFeatureStun)stunParamCfg).GetFeatureStun(); hp.StunRecoverTimeMax = stunParam.Time; hp.StunRecoverTime = stunParam.Time; hp.StunRecover = stunParam.RecoverSpeed; hp.StunMax.Value = stunParam.StunMax; hp.Stun.Value = 0; } } //基础属性 if (entity.hasProperty) { Util.SetProperty(entity, EProperty.BasicAttack, cfg.BasicAttack); Util.SetProperty(entity, EProperty.BasicStun, cfg.BasicStun); Util.SetProperty(entity, EProperty.StaggerDefLevel, (int)cfg.StaggerDefLevel); } } private static void BuildView(GameEntity entity, EntityParamViewFeature cfg) { var view = entity.view; if (!(cfg.Icon is null)) { var texture = Util.LoadDraft(cfg.Icon); var rect = new Rect(0, 0, texture.width, texture.height); //像素化 if (cfg.IsPixel) { texture.filterMode = FilterMode.Point; } var sp = Sprite.Create(texture, rect, new Vector2(0.5f, 0.5f), 64); view.SpriteRenderer.sprite = sp; } //缩放 var scale = cfg.Scale; view.TransformView.localScale = new Vector3(scale, scale, scale); var id = entity.iD; id.Data.Effect = cfg.Effect; id.Data.EffectCreate = cfg.EffectCreate; id.Data.EffectDestroy = cfg.EffectDestroy; if (!string.IsNullOrEmpty(cfg.Effect)) { Util.CastFollowEffect(cfg.Effect, entity.ID()); } if (!string.IsNullOrEmpty(cfg.EffectCreate)) { Util.CastHitEffect(cfg.EffectCreate, entity.ID()); } } private static void BuildBlessInteract(GameEntity entity, BlessInteractParamFeature cfg) { var interact = entity.interact; // interact.TargetId = ((EElementType)cfg.Element).ToString(); } private static void BuildBullet(GameEntity entity, BulletFeature cfg) { var bullet = entity.bullet; bullet.Timeline = cfg.Timeline; } private static void BuildMonster(GameEntity entity, EntityParamMonsterFeature cfg) { var ai = entity.aI; var view = entity.view; ai.BehaviorTree = BehaviorTreePoolManager.Instance.CreateAIEntity(entity, cfg.AIRes); var go = view.GameObject; var goMonsterInfo = go.GetComponent(); if (goMonsterInfo == null) { goMonsterInfo = go.AddComponent(); } goMonsterInfo.Tree = ai.BehaviorTree.AIObject.Tree(); } } }