初始化仓库

This commit is contained in:
SepComet
2026-02-07 19:38:49 +08:00
commit 88641dae11
1540 changed files with 371772 additions and 0 deletions
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 58efe0589d7e90f498c8bcbbf94c6be4
folderAsset: yes
timeCreated: 1528026151
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,53 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
using Definition.Enum;
using StarForce;
using UnityEngine;
namespace Entity.EntityData
{
[Serializable]
public abstract class AccessoryObjectData : EntityDataBase
{
[SerializeField]
private int m_OwnerId = 0;
[SerializeField]
private CampType m_OwnerCamp = CampType.Unknown;
public AccessoryObjectData(int entityId, int typeId, int ownerId, CampType ownerCamp)
: base(entityId, typeId)
{
m_OwnerId = ownerId;
m_OwnerCamp = ownerCamp;
}
/// <summary>
/// 拥有者编号。
/// </summary>
public int OwnerId
{
get
{
return m_OwnerId;
}
}
/// <summary>
/// 拥有者阵营。
/// </summary>
public CampType OwnerCamp
{
get
{
return m_OwnerCamp;
}
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 83cb841b7411a844581691d5547bf866
timeCreated: 1528026151
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,71 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
using Definition.Enum;
using StarForce;
using UnityEngine;
namespace Entity.EntityData
{
[Serializable]
public class BulletData : EntityDataBase
{
[SerializeField]
private int m_OwnerId = 0;
[SerializeField]
private CampType m_OwnerCamp = CampType.Unknown;
[SerializeField]
private int m_Attack = 0;
[SerializeField]
private float m_Speed = 0f;
public BulletData(int entityId, int typeId, int ownerId, CampType ownerCamp, int attack, float speed)
: base(entityId, typeId)
{
m_OwnerId = ownerId;
m_OwnerCamp = ownerCamp;
m_Attack = attack;
m_Speed = speed;
}
public int OwnerId
{
get
{
return m_OwnerId;
}
}
public CampType OwnerCamp
{
get
{
return m_OwnerCamp;
}
}
public int Attack
{
get
{
return m_Attack;
}
}
public float Speed
{
get
{
return m_Speed;
}
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 16371cc6e2112964d8b5bf7400c862cd
timeCreated: 1528026152
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,18 @@
namespace Entity.EntityData
{
public class CoinData : EntityDataBase
{
private int _value;
public CoinData(int value, int entityId, int typeId) : base(entityId, typeId)
{
_value = value;
}
public int Value
{
get => _value;
set => _value = value;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d9caee22d67a42018113acc77155d6ba
timeCreated: 1770292597
@@ -0,0 +1,33 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
using UnityEngine;
namespace Entity.EntityData
{
[Serializable]
public class EffectData : EntityDataBase
{
[SerializeField]
private float m_KeepTime = 0f;
public EffectData(int entityId, int typeId)
: base(entityId, typeId)
{
m_KeepTime = 3f;
}
public float KeepTime
{
get
{
return m_KeepTime;
}
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e5b93dcbe30421a429c196bda0af31ed
timeCreated: 1528026152
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 611437bd292819b439512f684e13c7e3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,56 @@
using System;
using DataTable;
using Definition.Enum;
using UnityEngine;
namespace Entity.EntityData
{
[Serializable]
public class EnemyData : TargetableObjectData
{
[SerializeField] private float _speedBase = 0;
[SerializeField] private int _dropCoin = 0;
[SerializeField] private int _dropExp = 0;
[SerializeField] private float _dropPercent = 0;
public EnemyData(int entityId, int typeId) : base(
entityId, typeId, CampType.Enemy)
{
DREnemy enemyRow = GameEntry.DataTable.GetDataTableRow<DREnemy>(typeId);
MaxHealthBase = enemyRow.MaxHealth;
SpeedBase = enemyRow.Speed;
DropCoin = enemyRow.DropCoin;
DropExp = enemyRow.DropExp;
DropPercent = enemyRow.DropPercent;
}
public override int MaxHealthBase { get; }
public float SpeedBase
{
get => _speedBase;
set => _speedBase = value;
}
public int DropCoin
{
get => _dropCoin;
set => _dropCoin = value;
}
public int DropExp
{
get => _dropExp;
set => _dropExp = value;
}
public float DropPercent
{
get => _dropPercent;
set => _dropPercent = value;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1b802c30cc274e04929b8659ec631e84
timeCreated: 1768890974
@@ -0,0 +1,62 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
using UnityEngine;
namespace Entity.EntityData
{
[Serializable]
public abstract class EntityDataBase
{
[SerializeField]
private int m_Id = 0;
[SerializeField]
private int m_TypeId = 0;
[SerializeField]
private Vector3 m_Position = Vector3.zero;
[SerializeField]
private Quaternion m_Rotation = Quaternion.identity;
public EntityDataBase(int entityId, int typeId)
{
m_Id = entityId;
m_TypeId = typeId;
}
/// <summary>
/// 实体编号。
/// </summary>
public int Id => m_Id;
/// <summary>
/// 实体类型编号。
/// </summary>
public int TypeId => m_TypeId;
/// <summary>
/// 实体位置。
/// </summary>
public Vector3 Position
{
get => m_Position;
set => m_Position = value;
}
/// <summary>
/// 实体朝向。
/// </summary>
public Quaternion Rotation
{
get => m_Rotation;
set => m_Rotation = value;
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: afb91fe3ed8105e4a96b7bd5917ecc2b
timeCreated: 1528026152
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,18 @@
namespace Entity.EntityData
{
public class ExpData : EntityDataBase
{
private int _value;
public ExpData(int value, int entityId, int typeId) : base(entityId, typeId)
{
_value = value;
}
public int Value
{
get => _value;
set => _value = value;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e0f6c8e117da49f1ad04fd8810882043
timeCreated: 1770292932
@@ -0,0 +1,19 @@
using System;
using DataTable;
using Definition.Enum;
namespace Entity.EntityData
{
[Serializable]
public class PlayerData : TargetableObjectData
{
private int _maxExp;
public PlayerData(int entityId, int typeId) : base(entityId, typeId, CampType.Player)
{
MaxHealthBase = MaxHealthBase;
}
public override int MaxHealthBase { get; }
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b69d3168ac4f442994f8dc4d906daa60
timeCreated: 1768890638
@@ -0,0 +1,40 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
using Definition.Enum;
using StarForce;
using UnityEngine;
namespace Entity.EntityData
{
[Serializable]
public abstract class TargetableObjectData : EntityDataBase
{
[SerializeField]
private CampType _camp = CampType.Unknown;
public TargetableObjectData(int entityId, int typeId, CampType camp)
: base(entityId, typeId)
{
_camp = camp;
}
/// <summary>
/// 角色阵营。
/// </summary>
public CampType Camp => _camp;
/// <summary>
/// 最大生命。
/// </summary>
public abstract int MaxHealthBase
{
get;
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f866c15cf3f2a45429251d4a66f70c77
timeCreated: 1528026152
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d8b2591453b7f0841940c8e45528f465
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,49 @@
using System;
using DataTable;
using Definition.DataStruct;
using Definition.Enum;
namespace Entity.EntityData
{
[Serializable]
public class WeaponData : AccessoryObjectData
{
private DRWeapon _drWeapon;
public WeaponData(int entityId, int typeId, int ownerId, CampType ownerCamp)
: base(entityId, typeId, ownerId, ownerCamp)
{
_drWeapon = GameEntry.DataTable.GetDataTableRow<DRWeapon>(TypeId);
}
/// <summary>
/// 攻击力。
/// </summary>
public int Attack => _drWeapon.Attack;
/// <summary>
/// 攻击间隔。
/// </summary>
public float Cooldown => _drWeapon.Cooldown;
/// <summary>
/// 攻击范围。
/// </summary>
public float AttackRange => _drWeapon.AttackRange;
/// <summary>
/// 攻击音效。
/// </summary>
public int AttackSoundId => _drWeapon.AttackSoundId;
/// <summary>
/// 额外参数。
/// </summary>
public string Params => _drWeapon.Pramas;
/// <summary>
/// 额外属性。
/// </summary>
public StatModifier[] Modifiers => _drWeapon.Modifiers;
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e813e3219579f834d8e619c17a8083d4
timeCreated: 1528026153
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,12 @@
using Definition.Enum;
namespace Entity.EntityData
{
public class WeaponKnifeData : WeaponData
{
public WeaponKnifeData(int entityId, int typeId, int ownerId, CampType ownerCamp) : base(entityId, typeId,
ownerId, ownerCamp)
{
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: da25d8e0669f0194d8f56f4283c67b38
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,143 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
using System.Collections.Generic;
using Definition;
using Entity.EntityData;
using UnityGameFramework.Runtime;
using DataTable;
using Definition.Enum;
using Game.Utility;
namespace Entity
{
public static class EntityExtension
{
// 关于 EntityId 的约定:
// 0 为无效
// 正值用于和服务器通信的实体(如玩家角色、NPC、怪等,服务器只产生正值)
// 负值用于本地生成的临时实体(如特效、FakeObject等)
private static int s_SerialId = -10;
private const string EntityNamespace = "Entity.";
private static Dictionary<string, Type> _typeDict;
static EntityExtension()
{
_typeDict = new Dictionary<string, Type>();
}
public static EntityBase GetGameEntity(this EntityComponent entityComponent, int entityId)
{
UnityGameFramework.Runtime.Entity entity = entityComponent.GetEntity(entityId);
if (entity == null)
{
return null;
}
return (EntityBase)entity.Logic;
}
public static void HideEntity(this EntityComponent entityComponent, EntityBase entity)
{
entityComponent.HideEntity(entity.Entity);
}
public static void AttachEntity(this EntityComponent entityComponent, EntityBase entityBase, int ownerId,
string parentTransformPath = null, object userData = null)
{
entityComponent.AttachEntity(entityBase.Entity, ownerId, parentTransformPath, userData);
}
public static void ShowPlayer(this EntityComponent entityComponent, PlayerData data)
{
entityComponent.ShowEntity(typeof(Player), "Player", Constant.AssetPriority.PlayerAsset, data);
}
public static void ShowEnemy(this EntityComponent entityComponent, EnemyData data)
{
string typeName = EntityNamespace + (EnemyType)data.TypeId;
if (!_typeDict.TryGetValue(typeName, out Type enemyType))
{
enemyType = Type.GetType(typeName);
if (enemyType == null)
{
Log.Warning("Can not load entity type '{0}'.", typeName);
return;
}
_typeDict.Add(typeName, enemyType);
}
entityComponent.ShowEntity(enemyType, "Enemy", Constant.AssetPriority.EnemyAsset, data);
}
public static void ShowWeapon(this EntityComponent entityComponent, WeaponData data)
{
string typeName = EntityNamespace + (WeaponType)data.TypeId;
if (!_typeDict.TryGetValue(typeName, out Type weaponType))
{
weaponType = Type.GetType(typeName);
if (weaponType == null)
{
Log.Warning("Can not load entity type '{0}'.", typeName);
return;
}
_typeDict.Add(typeName, weaponType);
}
entityComponent.ShowEntity(weaponType, "Weapon", Constant.AssetPriority.WeaponAsset, data);
}
public static void ShowBullet(this EntityComponent entityComponent, BulletData data)
{
entityComponent.ShowEntity(typeof(Bullet), "Bullet", Constant.AssetPriority.BulletAsset, data);
}
public static void ShowEffect(this EntityComponent entityComponent, EffectData data)
{
entityComponent.ShowEntity(typeof(Effect), "Effect", Constant.AssetPriority.EffectAsset, data);
}
public static void ShowCoin(this EntityComponent entityComponent, CoinData data)
{
entityComponent.ShowEntity(typeof(CoinEntity), "Drop", Constant.AssetPriority.EffectAsset, data);
}
public static void ShowExp(this EntityComponent entityComponent, ExpData data)
{
entityComponent.ShowEntity(typeof(ExpEntity), "Drop", Constant.AssetPriority.EffectAsset, data);
}
private static void ShowEntity(this EntityComponent entityComponent, Type logicType, string entityGroup,
int priority, EntityDataBase data)
{
if (data == null)
{
Log.Warning("Data is invalid.");
return;
}
DREntity drEntity = GameEntry.DataTable.GetDataTableRow<DREntity>(data.TypeId);
if (drEntity == null)
{
Log.Warning("Can not load entity id '{0}' from data table.", data.TypeId.ToString());
return;
}
entityComponent.ShowEntity(data.Id, logicType, AssetUtility.GetEntityAsset(drEntity.AssetName), entityGroup,
priority, data);
}
public static int GenerateSerialId(this EntityComponent entityComponent)
{
return --s_SerialId;
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 626632079980ad34595c3b43a062a664
timeCreated: 1528026153
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 74fbdf043ed3bc141a0a0b09756bc7d2
folderAsset: yes
timeCreated: 1528026153
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,53 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using Definition.DataStruct;
using Entity.EntityData;
using StarForce;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace Entity
{
/// <summary>
/// 子弹类。
/// </summary>
public class Bullet : EntityBase
{
[SerializeField] private BulletData m_BulletData = null;
public ImpactData GetImpactData()
{
//TODO:子弹的 AttackStat 不该为 null
return new ImpactData(m_BulletData.OwnerCamp, m_BulletData.Attack, null);
}
protected override void OnInit(object userData)
{
base.OnInit(userData);
}
protected override void OnShow(object userData)
{
base.OnShow(userData);
m_BulletData = userData as BulletData;
if (m_BulletData == null)
{
Log.Error("Bullet data is invalid.");
return;
}
}
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(elapseSeconds, realElapseSeconds);
CachedTransform.Translate(Vector3.forward * m_BulletData.Speed * elapseSeconds, Space.World);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 822be177ff3fd674fa34da0755f1a427
timeCreated: 1528026153
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,37 @@
using Entity.EntityData;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace Entity
{
public class CoinEntity : EntityBase
{
private CoinData _coinData;
protected override void OnShow(object userData)
{
base.OnShow(userData);
if (userData is CoinData coinData)
{
_coinData = coinData;
}
else
{
Log.Error("CoinEntity.OnShow() called with wrong type.");
}
this.CachedTransform.localScale = new Vector3(0.3f, 0.3f, 0.3f);
}
private void OnTriggerEnter(Collider other)
{
var player = other.GetComponent<Player>();
if (player != null && player.Available)
{
player.Coin += _coinData.Value;
GameEntry.Entity.HideEntity(this);
}
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0878ab0829c34f44a83d5e5a1eb586ea
timeCreated: 1770292173
@@ -0,0 +1,58 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using Entity;
using Entity.EntityData;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace Entity
{
/// <summary>
/// 特效类。
/// </summary>
public class Effect : EntityBase
{
[SerializeField]
private EffectData m_EffectData = null;
private float m_ElapseSeconds = 0f;
#if UNITY_2017_3_OR_NEWER
protected override void OnShow(object userData)
#else
protected internal override void OnShow(object userData)
#endif
{
base.OnShow(userData);
m_EffectData = userData as EffectData;
if (m_EffectData == null)
{
Log.Error("Effect data is invalid.");
return;
}
m_ElapseSeconds = 0f;
}
#if UNITY_2017_3_OR_NEWER
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
#else
protected internal override void OnUpdate(float elapseSeconds, float realElapseSeconds)
#endif
{
base.OnUpdate(elapseSeconds, realElapseSeconds);
m_ElapseSeconds += elapseSeconds;
if (m_ElapseSeconds >= m_EffectData.KeepTime)
{
GameEntry.Entity.HideEntity(this);
}
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c3e408851e9ea064bb8bc08fbb10b33f
timeCreated: 1528026154
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 81c9b48d9ff1bce45b91ffa040b1db2a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,12 @@
using Definition.DataStruct;
using Entity;
using UnityEngine;
public abstract class EnemyBase : TargetableObject
{
protected Transform _target;
public abstract override ImpactData GetImpactData();
public virtual void SetTarget(Transform target) => _target = target;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d33d6ac2d1874d4418780e3354e6b4e3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,115 @@
using Components;
using Definition.DataStruct;
using Entity.EntityData;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace Entity
{
public class MeleeEnemy : EnemyBase
{
private MovementComponent _movementComponent;
private float _attackRange = 1f;
private float _attackRangeSquared;
private EnemyData _meleeEnemyData;
private WeaponBase _weapon;
protected override TargetableObjectData _targetableObjectData => _meleeEnemyData;
public override ImpactData GetImpactData()
{
return new ImpactData(_meleeEnemyData.Camp, 0);
}
#region FSM
protected override void OnInit(object userData)
{
base.OnInit(userData);
_movementComponent = GetComponent<MovementComponent>();
_healthComponent = GetComponent<HealthComponent>();
}
protected override void OnShow(object userData)
{
base.OnShow(userData);
if (userData is EnemyData enemyData)
{
_meleeEnemyData = enemyData;
_healthComponent.OnInit(enemyData.MaxHealthBase);
_movementComponent.OnInit(_meleeEnemyData.SpeedBase, this.CachedTransform);
_movementComponent.SetMove(true);
_attackRangeSquared = _attackRange * _attackRange;
this.CachedTransform.position = enemyData.Position;
}
else
{
Log.Error($"Invalid data type. Data type: {userData?.GetType()}");
}
}
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(elapseSeconds, realElapseSeconds);
float distanceSquared = (this.CachedTransform.position - _target.position).sqrMagnitude;
if (distanceSquared < _attackRangeSquared)
{
// 攻击
_movementComponent.SetMove(false);
}
else
{
_movementComponent.SetMove(true);
_movementComponent.SetDirection(GetTargetDirection());
}
_movementComponent.OnUpdate(elapseSeconds, realElapseSeconds);
}
protected override void OnDead(EntityBase attacker)
{
if (Random.value < _meleeEnemyData.DropPercent)
{
var data = new CoinData(_meleeEnemyData.DropCoin, GameEntry.Entity.GenerateSerialId(), 10001)
{
Position = this.CachedTransform.position
};
GameEntry.Entity.ShowCoin(data);
}
if (Random.value < _meleeEnemyData.DropPercent)
{
var data = new ExpData(_meleeEnemyData.DropExp, GameEntry.Entity.GenerateSerialId(), 10002)
{
Position = this.CachedTransform.position
};
GameEntry.Entity.ShowExp(data);
}
base.OnDead(attacker);
}
protected override void OnHide(bool isShutdown, object userData)
{
_movementComponent.OnReset();
_healthComponent.OnReset();
base.OnHide(isShutdown, userData);
}
#endregion
private Vector3 GetTargetDirection()
{
return new Vector3(
_target.position.x - this.CachedTransform.position.x,
0f,
_target.position.z - this.CachedTransform.position.z
).normalized;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 112f2a17ab82438484782c9a763fdee1
timeCreated: 1768892870
@@ -0,0 +1,87 @@
using Components;
using Definition.DataStruct;
using Entity.EntityData;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace Entity
{
public class RemoteEnemy : EnemyBase
{
private float _speed;
private MovementComponent _movementComponent;
private float _attackRange = 1f;
private float _attackRangeSquared;
private EnemyData _remoteEnemyData;
protected override TargetableObjectData _targetableObjectData => _remoteEnemyData;
public override ImpactData GetImpactData()
{
return new ImpactData(_remoteEnemyData.Camp, 0);
}
protected override void OnInit(object userData)
{
base.OnInit(userData);
_movementComponent = GetComponent<MovementComponent>();
_healthComponent = GetComponent<HealthComponent>();
}
protected override void OnShow(object userData)
{
base.OnShow(userData);
if (userData is EnemyData enemyData)
{
_remoteEnemyData = enemyData;
_healthComponent.OnInit(enemyData.MaxHealthBase);
_movementComponent.OnInit(_remoteEnemyData.SpeedBase, this.CachedTransform);
_movementComponent.SetMove(true);
_attackRangeSquared = _attackRange * _attackRange;
this.CachedTransform.position = enemyData.Position;
}
else
{
Log.Error($"Invalid data type. Data type: {userData?.GetType()}");
}
}
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(elapseSeconds, realElapseSeconds);
float distanceSquared = (this.CachedTransform.position - _target.position).sqrMagnitude;
if (distanceSquared < _attackRangeSquared)
{
// 攻击
_movementComponent.SetMove(false);
}
else
{
_movementComponent.SetMove(true);
_movementComponent.SetDirection(GetTargetDirection());
}
_movementComponent.OnUpdate(elapseSeconds, realElapseSeconds);
}
protected override void OnHide(bool isShutdown, object userData)
{
_movementComponent.OnReset();
_healthComponent.OnReset();
base.OnHide(isShutdown, userData);
}
private Vector3 GetTargetDirection()
{
return new Vector3(
_target.position.x - this.CachedTransform.position.x,
0f,
_target.position.z - this.CachedTransform.position.z
).normalized;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b90e05d1e7a5475bb928b2445e113767
timeCreated: 1770209676
@@ -0,0 +1,82 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using Entity.EntityData;
using GameFramework;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace Entity
{
public abstract class EntityBase : EntityLogic
{
[SerializeField] private EntityDataBase _entityData = null;
public int Id => Entity.Id;
public Animation CachedAnimation { get; private set; }
protected override void OnInit(object userData)
{
base.OnInit(userData);
CachedAnimation = GetComponent<Animation>();
}
protected override void OnRecycle()
{
base.OnRecycle();
}
protected override void OnShow(object userData)
{
base.OnShow(userData);
_entityData = userData as EntityDataBase;
if (_entityData == null)
{
Log.Error("Entity data is invalid.");
return;
}
Name = Utility.Text.Format("[Entity {0}]", Id);
CachedTransform.localPosition = _entityData.Position;
CachedTransform.localRotation = _entityData.Rotation;
CachedTransform.localScale = Vector3.one;
}
protected override void OnHide(bool isShutdown, object userData)
{
base.OnHide(isShutdown, userData);
}
protected override void OnAttached(EntityLogic childEntity, Transform parentTransform, object userData)
{
base.OnAttached(childEntity, parentTransform, userData);
}
protected override void OnDetached(EntityLogic childEntity, object userData)
{
base.OnDetached(childEntity, userData);
}
protected override void OnAttachTo(EntityLogic parentEntity, Transform parentTransform, object userData)
{
base.OnAttachTo(parentEntity, parentTransform, userData);
}
protected override void OnDetachFrom(EntityLogic parentEntity, object userData)
{
base.OnDetachFrom(parentEntity, userData);
}
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(elapseSeconds, realElapseSeconds);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 878fbbe82b4bde944812bcb7c964cff8
timeCreated: 1528026154
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,36 @@
using Entity.EntityData;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace Entity
{
public class ExpEntity:EntityBase
{
private ExpData _expData;
protected override void OnShow(object userData)
{
base.OnShow(userData);
if (userData is ExpData expData)
{
_expData = expData;
}
else
{
Log.Error("expEntity.OnShow() called with wrong type.");
}
this.CachedTransform.localScale = new Vector3(0.3f, 0.3f, 0.3f);
}
private void OnTriggerEnter(Collider other)
{
var player = other.GetComponent<Player>();
if (player != null && player.Available)
{
player.Exp += _expData.Value;
GameEntry.Entity.HideEntity(this);
}
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ec4ae4b0a327442a88463eafd59c5b6e
timeCreated: 1770293001
@@ -0,0 +1,191 @@
using Components;
using CustomEvent;
using DataTable;
using Definition.DataStruct;
using Entity.EntityData;
using GameFramework.Event;
using UnityGameFramework.Runtime;
namespace Entity
{
public class Player : TargetableObject
{
protected override TargetableObjectData _targetableObjectData => _playerData;
private InputComponent _inputComponent;
private MovementComponent _movementComponent;
private StatComponent _statComponent;
private BackpackComponent _backpackComponent;
private PlayerData _playerData;
/// <summary>
/// 当前金币。
/// </summary>
private int _coin;
/// <summary>
/// 当前经验。
/// </summary>
private int _exp;
/// <summary>
/// 每级所需的经验。
/// tip: _expRequires[1] 表示 Lv 0 -> Lv 1 需要的经验
/// </summary>
private int[] _expRequires;
/// <summary>
/// 当前的角色等级。
/// </summary>
private int _currentLevel;
/// <summary>
/// 玩家是否启用。
/// </summary>
private bool _enable;
public int Coin
{
get => _coin;
set
{
GameEntry.Event.Fire(this, PlayerCoinChangeEventArgs.Create(value - _coin, value));
_coin = value;
}
}
public int Exp
{
get => _exp;
set
{
if (value >= _expRequires[_currentLevel + 1])
{
value -= _expRequires[_currentLevel + 1];
_currentLevel++;
}
GameEntry.Event.Fire(this, PlayerExpChangeEventArgs.Create(value, _expRequires[_currentLevel + 1]));
_exp = value;
}
}
public bool Enable
{
get => _enable;
set
{
if (value == _enable) return;
_movementComponent.SetMove(value);
_backpackComponent.SetWeaponState(value);
_inputComponent.SetListening(value);
}
}
public void InitRole(DRRole role)
{
// MovementComponent
_movementComponent.OnInit(role.Speed, this.CachedTransform, _statComponent);
_movementComponent.SetMove(true);
// HealthComponent
_healthComponent.OnInit(role.MaxHealth, _statComponent);
// BackpackComponent
Coin = role.Coin;
_backpackComponent.OnInit(this, role.WeaponCapacity);
GameEntry.Entity.ShowWeapon(new WeaponKnifeData(GameEntry.Entity.GenerateSerialId(), 201,
this.Id, _playerData.Camp));
// StatComponent
foreach (var modifier in role.InitialProperties)
{
_statComponent.AddModifier(modifier);
}
_expRequires = role.ExpRequires;
// Fire Events
GameEntry.Event.Fire(this,
PlayerHealthChangeEventArgs.Create(0, _healthComponent.CurrentHealth, _healthComponent.MaxHealth));
GameEntry.Event.Fire(this, PlayerExpChangeEventArgs.Create(0, 100));
GameEntry.Event.Fire(this,
PlayerCoinChangeEventArgs.Create(Coin, Coin));
}
#region FSM
public override ImpactData GetImpactData()
{
return new ImpactData(_playerData.Camp, 0, null, _healthComponent.DefenseStat, _healthComponent.DodgeStat);
}
protected override void OnInit(object userData)
{
base.OnInit(userData);
_inputComponent = GetComponent<InputComponent>();
_movementComponent = GetComponent<MovementComponent>();
_statComponent = GetComponent<StatComponent>();
_healthComponent = GetComponent<HealthComponent>();
_backpackComponent = GetComponent<BackpackComponent>();
}
protected override void OnShow(object userData)
{
base.OnShow(userData);
GameEntry.Event.Subscribe(ShowEntitySuccessEventArgs.EventId, ShowEntitySuccess);
_statComponent.OnInit();
if (userData is PlayerData playerData)
{
_playerData = playerData;
}
_inputComponent.OnInit();
_inputComponent.SetListening(true);
_currentLevel = 0;
}
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(elapseSeconds, realElapseSeconds);
_inputComponent.OnUpdate(elapseSeconds, realElapseSeconds);
_movementComponent.SetDirection(_inputComponent.Direction);
_movementComponent.OnUpdate(elapseSeconds, realElapseSeconds);
}
protected override void OnHide(bool isShutdown, object userData)
{
_inputComponent.OnReset();
_movementComponent.OnReset();
_healthComponent.OnReset();
_statComponent.OnReset();
_backpackComponent.OnReset();
base.OnHide(isShutdown, userData);
}
#endregion
#region Event Handlers
private void ShowEntitySuccess(object sender, GameEventArgs e)
{
if (!(e is ShowEntitySuccessEventArgs args)) return;
if (args.Entity.Logic is WeaponBase weapon)
{
_backpackComponent.AttachWeapon(weapon);
}
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3979cb10abff0944aad09de04ec7813a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,83 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using Components;
using Definition;
using Definition.DataStruct;
using Entity.EntityData;
using StarForce;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace Entity
{
/// <summary>
/// 可作为目标的实体类。
/// </summary>
public abstract class TargetableObject : EntityBase
{
protected abstract TargetableObjectData _targetableObjectData { get; }
public bool IsDead => _healthComponent.CurrentHealth <= 0;
protected HealthComponent _healthComponent;
public abstract ImpactData GetImpactData();
public void ApplyDamage(EntityBase attacker, int damageHP)
{
float fromHPRatio = _healthComponent.HealthRatio;
_healthComponent.TakeDamage(damageHP);
float toHPRatio = _healthComponent.HealthRatio;
if (fromHPRatio > toHPRatio)
{
GameEntry.HPBar.ShowHPBar(this, fromHPRatio, toHPRatio);
}
if (_healthComponent.CurrentHealth <= 0)
{
OnDead(attacker);
}
}
protected override void OnInit(object userData)
{
base.OnInit(userData);
_healthComponent = GetComponent<HealthComponent>();
}
protected override void OnShow(object userData)
{
base.OnShow(userData);
}
protected virtual void OnDead(EntityBase attacker)
{
GameEntry.Entity.HideEntity(this);
}
private void OnTriggerEnter(Collider other)
{
EntityBase entity = other.gameObject.GetComponent<EntityBase>();
if (entity == null)
{
return;
}
if (entity is TargetableObject && entity.Id < Id)
{
// 碰撞事件由 Id 大的一方处理
// 在这里规定所有的 Enemy 的 Id 均大于 0
// 而其他的 Entity (Player, Weapon, Bullet) 的 Id 均小于 0
return;
}
AIUtility.PerformCollision(this, entity);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4a1fd351b05d994459122be1a39507b1
timeCreated: 1528026154
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6b5f40df44fe005498fc03555871b8ad
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,83 @@
using System;
using Definition.DataStruct;
using Entity.EntityData;
using GameFramework;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace Entity
{
public enum WeaponStateType
{
Disabled,
Check,
Attack,
Transition,
Idle,
Check_OutRange,
Check_InRange,
}
/// <summary>
/// 武器类。
/// </summary>
public abstract class WeaponBase : EntityBase
{
protected const string AttachPoint = "Weapon Point";
protected bool _isAttacking = false;
protected bool _isEnabled = false;
public WeaponData WeaponData;
public bool IsAttacking => _isAttacking;
protected WeaponStateBase _currentState;
#region FSM
protected override void OnInit(object userData)
{
base.OnInit(userData);
}
//protected abstract void OnShow(object userData);
// {
// base.OnShow(userData);
//
// _weaponData = userData as WeaponData;
// if (_weaponData == null)
// {
// Log.Error("Weapon data is invalid.");
// return;
// }
// }
protected override void OnAttachTo(EntityLogic parentEntity, Transform parentTransform, object userData)
{
base.OnAttachTo(parentEntity, parentTransform, userData);
Name = Utility.Text.Format("Weapon of {0}", parentEntity.Name);
CachedTransform.localPosition = Vector3.zero;
}
#endregion
public abstract ImpactData GetImpactData();
protected abstract void Attack();
protected abstract void Check();
protected abstract void TransitionTo(WeaponStateType newState);
public void SetEnabled(bool value)
{
this._isEnabled = value;
TransitionTo(WeaponStateType.Idle);
}
}
public abstract class WeaponStateBase
{
public abstract WeaponStateType State { get; }
public abstract void OnInit(WeaponBase weapon);
public abstract void OnEnter();
public abstract void OnUpdate(float elapseSeconds, float realElapseSeconds);
public abstract void OnLeave();
public override string ToString() => State.ToString();
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: fc18f1a1232bb9644be1191168741922
timeCreated: 1528026154
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,332 @@
using System;
using System.Collections.Generic;
using Components;
using CustomComponent;
using Definition.DataStruct;
using Definition.Enum;
using DG.Tweening;
using Entity.EntityData;
using StarForce;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace Entity
{
public class WeaponKnife : WeaponBase
{
private WeaponKnifeData _weaponData;
private float _currAttackTimer = 0f;
private EnemyManagerComponent _enemy;
private EntityBase _target;
private float _sqrRange;
private Collider _collider;
private Rigidbody _rigidbody;
private Quaternion _cachedRotation;
[SerializeField] private float _rotateSpeed = 2f;
private Dictionary<WeaponStateType, WeaponStateBase> _weaponStates;
private StatProperty _attackStat = new();
private Action<StatModifier, bool> _attackStatCallback;
[SerializeField] private float attackDuration = 0.15f; // 戳刺持续时间
[SerializeField] private float returnDuration = 0.2f; // 回归持续时间
public override ImpactData GetImpactData()
{
return new ImpactData(_weaponData.OwnerCamp, _weaponData.Attack, _attackStat);
}
private void InitStates()
{
_weaponStates = new Dictionary<WeaponStateType, WeaponStateBase>
{
{ WeaponStateType.Idle, new IdleState() },
{ WeaponStateType.Check_InRange, new CheckInRangeState() },
{ WeaponStateType.Check_OutRange, new CheckOutRangeState() },
{ WeaponStateType.Attack, new AttackState() }
};
foreach (var state in _weaponStates.Values)
{
state.OnInit(this);
}
}
#region FSM Methods
protected override void Attack()
{
Vector3 targetPos = CachedTransform.position + CachedTransform.forward * _weaponData.AttackRange;
_isAttacking = true;
_collider.enabled = true;
_rigidbody.detectCollisions = true;
Transform parentTransform = CachedTransform.parent;
CachedTransform.SetParent(null);
var sequence = DOTween.Sequence();
sequence.Append(CachedTransform.DOMove(targetPos, attackDuration).SetEase(Ease.OutQuad));
sequence.AppendCallback(() =>
{
_collider.enabled = false;
_rigidbody.detectCollisions = false;
CachedTransform.SetParent(parentTransform);
});
sequence.Append(CachedTransform.DOLocalMove(Vector3.zero, returnDuration / 2f).SetEase(Ease.InQuad));
sequence.AppendCallback(() => { _isAttacking = false; });
}
protected override void Check()
{
_target = null;
float minSqrMagnitude = float.MaxValue;
var enemies = _enemy.Enemies;
foreach (var enemy in enemies)
{
if (enemy == null || !enemy.Available) continue;
float sqrMagnitude = AIUtility.GetSqrMagnitude(this, enemy);
if (minSqrMagnitude < sqrMagnitude) continue;
_target = enemy;
minSqrMagnitude = sqrMagnitude;
}
}
private void RotateToTarget(float elapseSeconds)
{
if (_target == null || !_target.Available) return;
Vector3 directionToTarget = (_target.CachedTransform.position - transform.position).normalized;
Quaternion targetRotation = Quaternion.LookRotation(directionToTarget, Vector3.up);
var quaternion = Quaternion.Slerp(CachedTransform.rotation, targetRotation, _rotateSpeed * elapseSeconds);
CachedTransform.rotation = quaternion;
}
private void RotateToOrigin(float elapseSeconds)
{
var quaternion = Quaternion.Slerp(CachedTransform.rotation, _cachedRotation, _rotateSpeed * elapseSeconds);
CachedTransform.rotation = quaternion;
}
protected override void TransitionTo(WeaponStateType state)
{
_currentState?.OnLeave();
_currentState = _weaponStates[state];
_currentState.OnEnter();
}
#endregion
#region FSM
protected override void OnShow(object userData)
{
base.OnShow(userData);
_weaponData = userData as WeaponKnifeData;
if (_weaponData == null)
{
Log.Error("WeaponKnife data is invalid.");
return;
}
_collider = GetComponent<Collider>();
_rigidbody = GetComponent<Rigidbody>();
_currAttackTimer = 0;
_enemy = GameEntry.EnemyManager;
_sqrRange = _weaponData.AttackRange * _weaponData.AttackRange;
_cachedRotation = transform.rotation;
_collider.enabled = false;
_rigidbody.detectCollisions = false;
if (_weaponData.OwnerCamp == CampType.Player)
this.gameObject.layer = LayerMask.NameToLayer("PlayerWeapon");
if (_weaponData.OwnerCamp == CampType.Enemy)
this.gameObject.layer = LayerMask.NameToLayer("EnemyWeapon");
InitStates();
TransitionTo(WeaponStateType.Idle);
}
protected override void OnAttachTo(EntityLogic parentEntity, Transform parentTransform, object userData)
{
base.OnAttachTo(parentEntity, parentTransform, userData);
if (parentEntity is Player player)
{
var statComponent = player.GetComponent<StatComponent>();
if (statComponent != null)
{
this._attackStat = statComponent.GetStat(StatType.Attack);
this._attackStatCallback = (modifier, b) => statComponent.UpdateStat(_attackStat, modifier, b);
statComponent.Subscribe(StatType.Attack, this._attackStatCallback);
}
}
}
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(elapseSeconds, realElapseSeconds);
if (!_isEnabled) return;
Log.Debug($"current state: {_currentState}");
_currentState?.OnUpdate(elapseSeconds, realElapseSeconds);
}
protected override void OnDetachFrom(EntityLogic parentEntity, object userData)
{
base.OnDetachFrom(parentEntity, userData);
if (parentEntity is Player player)
{
var statComponent = player.GetComponent<StatComponent>();
if (statComponent != null)
{
statComponent.Unsubscribe(StatType.Attack, this._attackStatCallback);
}
}
this._attackStat = null;
this._attackStatCallback = null;
}
#endregion
private class IdleState : WeaponStateBase
{
private WeaponKnife _weapon;
public override WeaponStateType State => WeaponStateType.Idle;
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife;
public override void OnEnter()
{
}
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
_weapon.Check();
_weapon.RotateToOrigin(elapseSeconds);
if (_weapon._target != null && _weapon._target.Available)
{
_weapon.TransitionTo(WeaponStateType.Check_OutRange);
}
}
public override void OnLeave()
{
}
}
private class CheckOutRangeState : WeaponStateBase
{
private WeaponKnife _weapon;
public override WeaponStateType State => WeaponStateType.Check_OutRange;
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife;
public override void OnEnter()
{
}
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
_weapon.Check();
_weapon.RotateToTarget(elapseSeconds);
if (_weapon._target == null || !_weapon._target.Available)
{
_weapon.TransitionTo(WeaponStateType.Idle);
return;
}
if (AIUtility.GetSqrMagnitude(_weapon._target, _weapon) < _weapon._sqrRange)
{
_weapon.TransitionTo(WeaponStateType.Check_InRange);
return;
}
}
public override void OnLeave()
{
}
}
private class CheckInRangeState : WeaponStateBase
{
private WeaponKnife _weapon;
public override WeaponStateType State => WeaponStateType.Check_InRange;
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife;
public override void OnEnter()
{
}
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
_weapon.Check();
_weapon.RotateToTarget(elapseSeconds);
_weapon._currAttackTimer += elapseSeconds;
if (_weapon._target == null || !_weapon._target.Available)
{
_weapon.TransitionTo(WeaponStateType.Idle);
return;
}
if (AIUtility.GetSqrMagnitude(_weapon._target, _weapon) >= _weapon._sqrRange)
{
_weapon.TransitionTo(WeaponStateType.Check_OutRange);
return;
}
if (_weapon._currAttackTimer >= _weapon._weaponData.Cooldown)
{
_weapon.TransitionTo(WeaponStateType.Attack);
return;
}
}
public override void OnLeave()
{
_weapon._currAttackTimer = 0;
}
}
private class AttackState : WeaponStateBase
{
private WeaponKnife _weapon;
public override WeaponStateType State => WeaponStateType.Attack;
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife;
public override void OnEnter()
{
_weapon.Attack();
}
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
if (!_weapon._isAttacking)
{
_weapon.TransitionTo(WeaponStateType.Check_InRange);
}
}
public override void OnLeave()
{
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bbf2e0cccf970934e82f8006d5be7846
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: