1
This commit is contained in:
@@ -51,6 +51,7 @@ namespace BITFALL.Entities.Armor
|
||||
if (_inventory is not null)
|
||||
{
|
||||
_inventory.OnUsedItem += OnUsedItem;
|
||||
_inventory.AllowUseItemFactory += OnAllowUse;
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +75,14 @@ namespace BITFALL.Entities.Armor
|
||||
}
|
||||
}
|
||||
|
||||
private bool OnAllowUse(IBasicItem arg)
|
||||
{
|
||||
if (OnTryEquip(arg) is false)
|
||||
{
|
||||
throw new InGameException("<color=yellow>无护甲或护甲已满</color>");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private bool OnTryEquip(IBasicItem arg)
|
||||
{
|
||||
if (arg is null) return true;
|
||||
|
@@ -27,7 +27,7 @@ namespace BITKit.Entities.Player.Character
|
||||
private readonly List<Renderer> fpvRenderer = new();
|
||||
private readonly List<Renderer> tpvRenderer = new();
|
||||
private readonly List<Renderer> fpvOverrideRenderers = new();
|
||||
private readonly List<Renderer> tpvRendererGroup = new();
|
||||
private readonly List<Renderer> tpvOverrideRenderers = new();
|
||||
|
||||
[Header(Constant.Header.Reference)]
|
||||
[SerializeReference, SubclassSelector] public IReference getDamage;
|
||||
@@ -44,29 +44,31 @@ namespace BITKit.Entities.Player.Character
|
||||
|
||||
[Inject(true)] private IEntityMovement _movement;
|
||||
|
||||
private Renderer[] _tpvRendererGroup;
|
||||
|
||||
private readonly ValidHandle allowFPVOverride = new();
|
||||
private readonly IntervalUpdate _freezeInterval=new (0.01f);
|
||||
private bool _isDirty;
|
||||
private bool _lock;
|
||||
|
||||
private void OnCosmeticsChange()
|
||||
{
|
||||
_lock = true;
|
||||
}
|
||||
|
||||
public override void OnAwake()
|
||||
{
|
||||
base.OnAwake();
|
||||
if(cosmeticService is not null)
|
||||
cosmeticService.OnCosmeticsChanged += Rebuild;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
if (cosmeticService is not null)
|
||||
{
|
||||
cosmeticService.OnCosmeticsChange += OnCosmeticsChange;
|
||||
cosmeticService.OnCosmeticsChanged += OnCosmeticsChanged;
|
||||
}
|
||||
|
||||
if (_health is not null)
|
||||
{
|
||||
_health.OnSetAlive += _ => UpdateMeshState();
|
||||
_health.OnSetAlive += SetDirty;
|
||||
_health.OnDamageRelease += OnDamageRelease;
|
||||
}
|
||||
|
||||
if (_cameraService is not null)
|
||||
_cameraService.OnCameraActivated += _ => UpdateMeshState();
|
||||
_cameraService.OnCameraActivated += SetDirty;
|
||||
|
||||
if (_entityOverride is not null)
|
||||
_entityOverride.OnOverride += _ =>
|
||||
@@ -74,7 +76,8 @@ namespace BITKit.Entities.Player.Character
|
||||
UpdateMeshState();
|
||||
allowFPVOverride.SetElements(_entityOverride, _);
|
||||
};
|
||||
_tpvRendererGroup = tpvRendererGroup.SelectMany(x => x.GetComponentsInChildren<Renderer>(true)).ToArray();
|
||||
|
||||
|
||||
|
||||
if (_equipment is not null)
|
||||
{
|
||||
@@ -108,31 +111,38 @@ namespace BITKit.Entities.Player.Character
|
||||
{
|
||||
foreach (var x in fpvOverrideRenderers)
|
||||
{
|
||||
x.enabled = value;
|
||||
try
|
||||
{
|
||||
x.enabled = value;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// if (_equipment is not null)
|
||||
// allowFPVOverride.AddElement(_equipment);
|
||||
|
||||
Rebuild();
|
||||
}
|
||||
|
||||
public override void OnPlayerInitialized()
|
||||
public override void OnDestroyComponent()
|
||||
{
|
||||
base.OnDestroyComponent();
|
||||
if (cosmeticService is null) return;
|
||||
cosmeticService.OnCosmeticsChange -= OnCosmeticsChange;
|
||||
cosmeticService.OnCosmeticsChanged -= OnCosmeticsChanged;
|
||||
}
|
||||
|
||||
public override void OnUpdate(float deltaTime)
|
||||
{
|
||||
if (!_isDirty || _lock || !_freezeInterval.AllowUpdateWithoutReset) return;
|
||||
_isDirty = false;
|
||||
UpdateMeshState();
|
||||
}
|
||||
public override void OnPlayerDispose()
|
||||
{
|
||||
SetFPV(false);
|
||||
}
|
||||
// private void OnSetHP(int hp)
|
||||
// {
|
||||
// UnityEntity.Invoke<string>(Constant.Animation.Play, getDamage.Value);
|
||||
// }
|
||||
|
||||
private void OnDamageRelease(DamageMessage damageMessage)
|
||||
{
|
||||
UnityEntity.Invoke<string>(Constant.Animation.Play, getDamage.Value);
|
||||
if (getDamage is not null)
|
||||
UnityEntity.Invoke<string>(Constant.Animation.Play, getDamage.Value);
|
||||
}
|
||||
|
||||
private void UpdateMeshState()
|
||||
@@ -170,7 +180,7 @@ namespace BITKit.Entities.Player.Character
|
||||
{
|
||||
x.shadowCastingMode = shadowMode;
|
||||
}
|
||||
foreach (var x in _tpvRendererGroup)
|
||||
foreach (var x in tpvOverrideRenderers)
|
||||
{
|
||||
x.shadowCastingMode =
|
||||
_entityOverride is not null
|
||||
@@ -179,33 +189,44 @@ namespace BITKit.Entities.Player.Character
|
||||
}
|
||||
}
|
||||
[BIT]
|
||||
private async void Rebuild()
|
||||
private void OnCosmeticsChanged()
|
||||
{
|
||||
_lock = true;
|
||||
BITAppForUnity.ThrowIfNotPlaying();
|
||||
await UniTask.Delay(100);
|
||||
await UniTask.SwitchToMainThread();
|
||||
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||
fpvRenderer.Clear();
|
||||
tpvRenderer.Clear();
|
||||
fpvOverrideRenderers.Clear();
|
||||
tpvRendererGroup.Clear();
|
||||
tpvOverrideRenderers.Clear();
|
||||
|
||||
var _tpvOverrideRenderers = new List<Transform>();
|
||||
foreach (var _tag in GetComponentsInChildren<Tag>(true))
|
||||
{
|
||||
if (_tag.TryGetComponent<Renderer>(out var _renderer) is false) continue;
|
||||
var tags = _tag.GetTags();
|
||||
if (tags.Contains(Player_Mesh_Type_TPV_Group))
|
||||
_tpvOverrideRenderers.Add(_tag.transform);
|
||||
if (_tag.TryGetComponent<Renderer>(out var _renderer) is false) continue;
|
||||
if (tags.Contains(Player_Mesh_Type_FPV))
|
||||
fpvRenderer.Add(_renderer);
|
||||
if (tags.Contains(Player_Mesh_Type_TPV))
|
||||
tpvRenderer.Add(_renderer);
|
||||
if (tags.Contains(Player_Mesh_Type_FPVOverride))
|
||||
fpvOverrideRenderers.Add(_renderer);
|
||||
if (tags.Contains(Player_Mesh_Type_TPV_Group))
|
||||
tpvRendererGroup.Add(_renderer);
|
||||
}
|
||||
|
||||
var tpvRenderers = _tpvOverrideRenderers.SelectMany(x => x.GetComponentsInChildren<Renderer>(true));
|
||||
tpvOverrideRenderers.Clear();
|
||||
tpvOverrideRenderers.AddRange(tpvRenderers);
|
||||
UpdateMeshState();
|
||||
allowFPVOverride.Invoke();
|
||||
|
||||
_lock = false;
|
||||
_isDirty = false;
|
||||
}
|
||||
|
||||
private void SetDirty(bool any) => SetDirty();
|
||||
private void SetDirty()
|
||||
{
|
||||
_freezeInterval.Reset();
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -12,9 +12,34 @@ namespace BITFALL.Entities.Inventory
|
||||
/// 已使用Item的回调
|
||||
/// </summary>
|
||||
event Action<IBasicItem> OnUsedItem;
|
||||
/// <summary>
|
||||
/// 尝试使用Item的方法,返回成功后将使用Item
|
||||
/// </summary>
|
||||
bool TryUseItem(IBasicItem item);
|
||||
/// <summary>
|
||||
/// 尝试使用Item的回调
|
||||
/// </summary>
|
||||
event Func<IBasicItem,bool> TryUseItemFactory;
|
||||
/// <summary>
|
||||
/// 允许使用Item的回调,调用后由调用方决定是否使用Item
|
||||
/// </summary>
|
||||
event Func<IBasicItem, bool> AllowUseItemFactory;
|
||||
/// <summary>
|
||||
/// 检查是否允许使用Item
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
bool AllowUseItem(IBasicItem item);
|
||||
/// <summary>
|
||||
/// 无条件使用Item
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
void UseItem(IBasicItem item);
|
||||
/// <summary>
|
||||
/// 尝试设置Item
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
bool TrySetItem(IBasicItem item);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BITFALL.Cosmetic;
|
||||
using BITKit;
|
||||
using BITKit.Entities;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks.Triggers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITFALL.Entities.Cosmetic
|
||||
{
|
||||
public class CosmeticArmColorBehaviour : EntityBehavior
|
||||
{
|
||||
[Inject(true)] private ICosmeticService _cosmeticService;
|
||||
public override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
_cosmeticService.OnCosmeticsChange += OnCosmeticsChange;
|
||||
}
|
||||
public override void OnDestroyComponent()
|
||||
{
|
||||
base.OnDestroyComponent();
|
||||
_cosmeticService.OnCosmeticsChange -= OnCosmeticsChange;
|
||||
}
|
||||
private async void OnCosmeticsChange()
|
||||
{
|
||||
await UniTask.NextFrame();
|
||||
await UniTask.NextFrame();
|
||||
await UniTask.NextFrame();
|
||||
if(destroyCancellationToken.IsCancellationRequested) return;
|
||||
foreach (var cosmetic in _cosmeticService.Modified.Values)
|
||||
{
|
||||
foreach (var cosmeticContent in cosmetic.As<ICosmetic>().Contents)
|
||||
{
|
||||
if(cosmeticContent is not CosmeticArmColorContent armColorContent) continue;
|
||||
foreach (var x in GetComponentsInChildren<Tag>())
|
||||
{
|
||||
if (x.GetTags().Contains("c_weapon_arm") is false) continue;
|
||||
if (x.TryGetComponent<Renderer>(out var _renderer))
|
||||
{
|
||||
|
||||
foreach (var material in _renderer.materials)
|
||||
{
|
||||
material.color = armColorContent.Color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BITFALL.Cosmetic;
|
||||
using BITKit;
|
||||
using BITKit.Entities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITFALL.Entities.Cosmetic
|
||||
{
|
||||
public class CosmeticArmModelBehaviour : EntityBehavior
|
||||
{
|
||||
[Inject] private ICosmeticService _cosmeticService;
|
||||
public override void OnAwake()
|
||||
{
|
||||
base.OnAwake();
|
||||
_cosmeticService.OnCosmeticsChange += OnCosmeticsChange;
|
||||
}
|
||||
public override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
OnCosmeticsChange();
|
||||
}
|
||||
|
||||
public override void OnDestroyComponent()
|
||||
{
|
||||
base.OnDestroyComponent();
|
||||
_cosmeticService.OnCosmeticsChange -= OnCosmeticsChange;
|
||||
}
|
||||
|
||||
private void OnCosmeticsChange()
|
||||
{
|
||||
foreach (var x in _cosmeticService
|
||||
.Modified
|
||||
.Values
|
||||
.OfType<ICosmetic>()
|
||||
.SelectMany(x=>x.Contents)
|
||||
.OfType<CosmeticArmModelContent>()
|
||||
)
|
||||
{
|
||||
foreach (var tag in GetComponentsInChildren<Tag>())
|
||||
{
|
||||
if(tag.GetTags().Contains("c_weapon_arm") is false) continue;
|
||||
if(tag.TryGetComponent<SkinnedMeshRenderer>(out var _renderer))
|
||||
{
|
||||
_renderer.sharedMaterials = x.SkinnedMeshRenderer.sharedMaterials;
|
||||
|
||||
var bones = x.SkinnedMeshRenderer.bones;
|
||||
|
||||
for (var i = 0; i < bones.Length; i++)
|
||||
{
|
||||
bones[i] = CosmeticModelBehaviour.GetRootBoneByName(_renderer.rootBone, bones[i].name);
|
||||
}
|
||||
|
||||
_renderer.sharedMesh = x.SkinnedMeshRenderer.sharedMesh;
|
||||
_renderer.bones = bones;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -13,37 +13,52 @@ namespace BITFALL.Entities.Cosmetic
|
||||
public class CosmeticModelBehaviour : EntityBehavior
|
||||
{
|
||||
[Inject(true)] private ICosmeticService _cosmeticService;
|
||||
[SerializeField] private SkinnedMeshRenderer[] currentRenderers;
|
||||
[SerializeField] private Transform armature;
|
||||
[SerializeField] private Transform current;
|
||||
[SerializeField] private Transform meshRoot;
|
||||
[SerializeField] private Animator animator;
|
||||
public override void OnAwake()
|
||||
{
|
||||
if (_cosmeticService is null) return;
|
||||
|
||||
_cosmeticService.OnCosmeticsChange += OnCosmeticsChange;
|
||||
_cosmeticService.OnCosmeticsChanged += OnCosmeticsChanged;
|
||||
destroyCancellationToken.Register(() => _cosmeticService.OnCosmeticsChanged -= OnCosmeticsChanged);
|
||||
}
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
OnCosmeticsChanged();
|
||||
destroyCancellationToken.Register(() =>
|
||||
{
|
||||
_cosmeticService.OnCosmeticsChange -= OnCosmeticsChange;
|
||||
_cosmeticService.OnCosmeticsChanged -= OnCosmeticsChanged;
|
||||
});
|
||||
}
|
||||
|
||||
private void OnCosmeticsChanged()
|
||||
{
|
||||
animator.Rebind();
|
||||
}
|
||||
public override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
if(current.TryGetComponent<Animator>(out var newAnimator))
|
||||
{
|
||||
Destroy(newAnimator);
|
||||
}
|
||||
OnCosmeticsChange();
|
||||
OnCosmeticsChanged();
|
||||
}
|
||||
private void OnCosmeticsChange()
|
||||
{
|
||||
foreach (var cosmetic in _cosmeticService.Modified.Values.OfType<ICosmetic>())
|
||||
{
|
||||
foreach (var content in cosmetic.Contents.OfType<CosmeticModelContent>())
|
||||
{
|
||||
foreach (var _renderer in currentRenderers)
|
||||
var instance = Instantiate(content.Model,meshRoot);
|
||||
instance.transform.localPosition = Vector3.zero;
|
||||
instance.transform.localRotation = Quaternion.identity;
|
||||
if (instance.TryGetComponent<Animator>(out var newAnimator))
|
||||
{
|
||||
Destroy(_renderer.gameObject);
|
||||
animator.avatar = newAnimator.avatar;
|
||||
Destroy(newAnimator);
|
||||
}
|
||||
var instance = Instantiate(content.Model);
|
||||
currentRenderers = instance.GetComponentsInChildren<SkinnedMeshRenderer>(true);
|
||||
TransferSkinnedMeshes(currentRenderers, meshRoot, armature);
|
||||
Destroy(instance);
|
||||
Destroy(current.gameObject);
|
||||
current = instance.transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +95,7 @@ namespace BITFALL.Entities.Cosmetic
|
||||
}
|
||||
|
||||
}
|
||||
private static Transform GetRootBoneByName(Component parentTransform, string name)
|
||||
public static Transform GetRootBoneByName(Component parentTransform, string name)
|
||||
{
|
||||
return parentTransform.GetComponentsInChildren<Transform>().FirstOrDefault(transformChild => transformChild.name == name);
|
||||
}
|
||||
|
@@ -21,5 +21,11 @@ namespace BITFALL.Entities.Cosmetic
|
||||
base.Initialize(_entity);
|
||||
_entity.As<Entity>().AddService<ICosmeticService>(cosmeticService);
|
||||
}
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
cosmeticService.SetDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ using BITFALL.Entities.Inventory;
|
||||
using BITFALL.Player.Equip;
|
||||
using BITFALL.Player.Inventory;
|
||||
using BITKit.Entities.Player;
|
||||
using BITKit.UX;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using UnityEditor;
|
||||
@@ -58,13 +59,16 @@ namespace BITFALL.Entities.Equipment
|
||||
private ImprovisedServiceInterface _improvisedService;
|
||||
[Inject]
|
||||
private IEntityEquipmentContainer _equipmentContainer;
|
||||
|
||||
[Inject]
|
||||
private IEquipService _equipService;
|
||||
[Inject(true)]
|
||||
private InputActionGroup _inputActionGroup;
|
||||
[Inject(true)]
|
||||
private IUXPopup _uxPopup;
|
||||
|
||||
private readonly List<int> _blockList=new();
|
||||
|
||||
[Inject(true)] private InputActionGroup _inputActionGroup;
|
||||
|
||||
|
||||
private readonly Optional<int> playerChoose = new ();
|
||||
|
||||
@@ -120,7 +124,28 @@ namespace BITFALL.Entities.Equipment
|
||||
|
||||
private void OnScroll(InputAction.CallbackContext obj)
|
||||
{
|
||||
|
||||
if (BITAppForUnity.AllowCursor) return;
|
||||
if (obj.performed is false) return;
|
||||
var value = obj.ReadValue<Vector2>().y;
|
||||
if (playerChoose.Allow is false)
|
||||
{
|
||||
if (equips.ContainsKey(1))
|
||||
{
|
||||
playerChoose.SetValueThenAllow(1);
|
||||
Equip(1);
|
||||
}else if (equips.ContainsKey(2))
|
||||
{
|
||||
playerChoose.SetValueThenAllow(2);
|
||||
Equip(2);
|
||||
}
|
||||
}
|
||||
//Debug.Log(playerChoose.Value);
|
||||
var nextChoose = playerChoose.Value is 1 ? 2 : 1;
|
||||
if (equips.ContainsKey(nextChoose))
|
||||
{
|
||||
playerChoose.SetValueThenAllow(nextChoose);
|
||||
Equip(nextChoose);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -301,36 +326,42 @@ namespace BITFALL.Entities.Equipment
|
||||
}
|
||||
private void OnTactics(InputAction.CallbackContext obj)
|
||||
{
|
||||
|
||||
switch(obj)
|
||||
{
|
||||
case {interaction:TapInteraction, performed: true}:
|
||||
Equip<EquipmentAsTactics>();
|
||||
break;
|
||||
}
|
||||
// switch(obj)
|
||||
// {
|
||||
// case {interaction:TapInteraction, performed: true}:
|
||||
// Equip<EquipmentAsTactics>();
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
public void Throw(InputAction.CallbackContext context)
|
||||
{
|
||||
//Debug.Log(context);
|
||||
switch (context)
|
||||
{
|
||||
case { interaction: HoldInteraction, performed: true }:
|
||||
if (currentEquip is null) return;
|
||||
if (equips.TryGetAny(x => x.Value.AddressablePath == currentEquip.AddressablePath, out var pair))
|
||||
{
|
||||
if (_inventory.DropOrSpawn(currentEquip))
|
||||
{
|
||||
equips.Remove(pair.Key);
|
||||
_equipment.EntryEquip((IBasicItem)null);
|
||||
currentEquip = null;
|
||||
UpdateEquip();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case { interaction: TapInteraction, performed: true }:
|
||||
case {interaction:TapInteraction, started: true}:
|
||||
Equip<EquipmentAsThrow>();
|
||||
break;
|
||||
}
|
||||
// switch (context)
|
||||
// {
|
||||
// case { interaction: HoldInteraction, performed: true }:
|
||||
// if (currentEquip is null) return;
|
||||
// if (equips.TryGetAny(x => x.Value.AddressablePath == currentEquip.AddressablePath, out var pair))
|
||||
// {
|
||||
// if (_inventory.DropOrSpawn(currentEquip))
|
||||
// {
|
||||
// equips.Remove(pair.Key);
|
||||
// _equipment.EntryEquip((IBasicItem)null);
|
||||
// currentEquip = null;
|
||||
// UpdateEquip();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
// case { interaction: TapInteraction, performed: true }:
|
||||
// Equip<EquipmentAsThrow>();
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
public void OnRemove(IBasicItem item)
|
||||
{
|
||||
@@ -417,6 +448,19 @@ namespace BITFALL.Entities.Equipment
|
||||
{
|
||||
if(_knockdown.IsKnockdown && item.Value.GetAssetable().AllowUseWhileKnocked is false) return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (_inventory.AllowUseItem(item.Value) is false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (InGameException e)
|
||||
{
|
||||
_uxPopup?.Popup(e.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
_improvisedService.TryUnEquipImprovised(out _);
|
||||
Equip(item.Value);
|
||||
return true;
|
||||
|
@@ -65,6 +65,7 @@ namespace BITKit.Entities
|
||||
OnItemApplied(value);
|
||||
}
|
||||
}
|
||||
public AssetableItem ScriptableItem => item;
|
||||
private IBasicItem _item;
|
||||
//public IDictionary<string, float> AnimationProperties = null;
|
||||
|
||||
@@ -82,6 +83,8 @@ namespace BITKit.Entities
|
||||
[Inject(true)] protected IEntityInventory _inventory;
|
||||
[Inject(true)] protected IUXPopup _uxPopup;
|
||||
|
||||
public IEntityInventory Inventory=>_inventory;
|
||||
public IUXPopup UXPopup=>_uxPopup;
|
||||
public override void Initialize()
|
||||
{
|
||||
SearchKey = new []{C_Weapon,item.Name};
|
||||
@@ -123,19 +126,25 @@ namespace BITKit.Entities
|
||||
vfxPlayer.enabled = false;
|
||||
}
|
||||
|
||||
public virtual UniTask ExitAsync()
|
||||
public virtual async UniTask ExitAsync()
|
||||
{
|
||||
AllowRendering.RemoveElement(this);
|
||||
|
||||
return UniTask.CompletedTask;
|
||||
while (AnimancerComponent.IsPlaying())
|
||||
{
|
||||
await UniTask.NextFrame();
|
||||
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual async void Exited()
|
||||
{
|
||||
if (!cameraTransform) return;
|
||||
AllowRendering.RemoveElement(this);
|
||||
if (cameraTransform)
|
||||
{
|
||||
cameraTransform.localPosition = default;
|
||||
cameraTransform.localRotation = _initialCameraRotation;
|
||||
}
|
||||
await UniTask.NextFrame(destroyCancellationToken);
|
||||
cameraTransform.localPosition = default;
|
||||
cameraTransform.localRotation = _initialCameraRotation;
|
||||
|
||||
|
||||
if (animancerComponent)
|
||||
{
|
||||
@@ -171,7 +180,11 @@ namespace BITKit.Entities
|
||||
_modify.AllowModify.SetDisableElements(this, !x);
|
||||
});
|
||||
if (animancerComponent)
|
||||
{
|
||||
animancerComponent.Animator.enabled = false;
|
||||
animancerComponent.enabled = false;
|
||||
}
|
||||
|
||||
AllowRendering.Invoke();
|
||||
if (cameraTransform)
|
||||
_initialCameraRotation = cameraTransform.localRotation;
|
||||
@@ -229,6 +242,7 @@ namespace BITKit.Entities
|
||||
{
|
||||
if (IsEntered is false) return;
|
||||
if (item is not AssetableEquip equip) return;
|
||||
UnityEntity.Invoke(Constant.Animation.OnEvent, eventName);
|
||||
switch (eventName)
|
||||
{
|
||||
case "Melee":
|
||||
@@ -368,7 +382,7 @@ namespace BITKit.Entities
|
||||
equips.Entry(_prioritySelector.Current);
|
||||
if (equips.index is not -1)
|
||||
{
|
||||
equips.list[equips.index].Item = CurrentItem;
|
||||
//equips.list[equips.index].Item = CurrentItem;
|
||||
}
|
||||
if (equips.TryGetEntried(out entryComplete))
|
||||
{
|
||||
|
@@ -28,6 +28,12 @@ namespace BITFALL
|
||||
{
|
||||
var health = UnityEntity.Get<IHealth>();
|
||||
health.OnSetAlive += OnSetAlive;
|
||||
_inventory.AllowUseItemFactory += OnAllowUse;
|
||||
}
|
||||
|
||||
private bool OnAllowUse(IBasicItem arg)
|
||||
{
|
||||
return Equipment.Values.Any(x => x.Id == arg?.Id) ;
|
||||
}
|
||||
|
||||
private void OnSetAlive(bool obj)
|
||||
@@ -75,6 +81,7 @@ namespace BITFALL
|
||||
OnDeEquip?.Invoke(pair.Key, pair.Value);
|
||||
_inventory.UseItem(pair.Value);
|
||||
|
||||
//自动补齐
|
||||
if (_inventory.TryGetItem(x => x.AddressablePath == pair.Value.AddressablePath, out var item))
|
||||
{
|
||||
Equip(pair.Key, item);
|
||||
|
@@ -43,6 +43,7 @@ namespace BITFALL
|
||||
public event Action<IBasicItem> OnUsedItem;
|
||||
public event Action<IBasicItem> OnRemove;
|
||||
public event Func<IBasicItem, bool> TryUseItemFactory;
|
||||
public event Func<IBasicItem, bool> AllowUseItemFactory;
|
||||
public event Action<IBasicItem> OnSet;
|
||||
public event Action<IBasicItem> OnDrop;
|
||||
public event Action<IBasicItemContainer> OnRebuild;
|
||||
@@ -82,6 +83,11 @@ namespace BITFALL
|
||||
return isUsed ||TryUseItemFactory is not null && TryUseItemFactory.CastAsFunc().Any(x => x.Invoke(item));
|
||||
}
|
||||
|
||||
public bool AllowUseItem(IBasicItem item)
|
||||
{
|
||||
return AllowUseItemFactory.CastAsFunc().Any(func => func.Invoke(item));
|
||||
}
|
||||
|
||||
public void UseItem(IBasicItem item)
|
||||
{
|
||||
if(item.GetAssetable().TryGetProperty<ICustomItemBehavior>(out var customItemBehavior))
|
||||
|
@@ -7,7 +7,8 @@
|
||||
"GUID:0a8b74b3309f0cc44bdd9a796253baef",
|
||||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:7efac18f239530141802fb139776f333"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
@@ -23,6 +23,8 @@ namespace BITKit.Entities
|
||||
[SerializeReference, SubclassSelector, Inject(true)]
|
||||
private IMeleeService meleeService;
|
||||
|
||||
[Inject(true)] private IHealth _health;
|
||||
|
||||
[Inject(true)] private IEntityOverride entityOverride;
|
||||
private readonly IntervalUpdate disableMelee = new(0.64f);
|
||||
|
||||
@@ -63,6 +65,7 @@ namespace BITKit.Entities
|
||||
|
||||
private void AnimationEventInternal(string actionName)
|
||||
{
|
||||
if (_health is { IsAlive: false }) return;
|
||||
switch (actionName)
|
||||
{
|
||||
case "Melee":
|
||||
|
@@ -19,6 +19,7 @@ namespace BITFALL.Movement.MotionBased
|
||||
|
||||
[Inject] private IEntityOverride _override;
|
||||
[Inject] private IHealth _health;
|
||||
|
||||
|
||||
private string lastAnimationName;
|
||||
public override void OnStart()
|
||||
|
@@ -75,6 +75,8 @@ namespace BITFALL.Movement.MotionBased
|
||||
_override.OnOverride += OnOverride;
|
||||
|
||||
_isAnimatorRoot = animancerComponent.Animator.transform == transform;
|
||||
|
||||
TransitionState<Walk>();
|
||||
}
|
||||
|
||||
private void OnSetAlive(bool obj)
|
||||
|
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "BITFALL.Entities.Physics.Runtime",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:709caf8d7fb6ef24bbba0ab9962a3ad0",
|
||||
"GUID:a3de65b07192e7d49bad7b4032d681de",
|
||||
"GUID:7efac18f239530141802fb139776f333",
|
||||
"GUID:2b6752324f5c76d4cad13e2095c77b9e"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
218
Assets/Artists/Scripts/Entities/Physics/EntityPhysics.cs
Normal file
218
Assets/Artists/Scripts/Entities/Physics/EntityPhysics.cs
Normal file
@@ -0,0 +1,218 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BITFALL.Cosmetic;
|
||||
using BITKit;
|
||||
using BITKit.Entities;
|
||||
using BITKit.Entities.Physics;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
namespace BITFALL.Entities
|
||||
{
|
||||
[CustomType(typeof(IEntityPhysics))]
|
||||
public class EntityPhysics : EntityBehavior,IEntityPhysics
|
||||
{
|
||||
[SerializeField] private Animator animator;
|
||||
|
||||
private Rigidbody[] rigidbodies=Array.Empty<Rigidbody>();
|
||||
private Collider[] colliders=Array.Empty<Collider>();
|
||||
private Joint[] joints=Array.Empty<Joint>();
|
||||
private new Rigidbody rigidbody;
|
||||
|
||||
[Inject(true)] private IHealth _health;
|
||||
[Inject(true)] private IEntityOverride _override;
|
||||
[Inject(true)] private ICosmeticService _cosmeticService;
|
||||
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointXMotions=new();
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointYMotions=new();
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointZMotions=new();
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointAngularXMotions=new();
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointAngularYMotions=new();
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointAngularZMotions=new();
|
||||
|
||||
private readonly IntervalUpdate _intervalUpdate=new(0.01f);
|
||||
private bool isDirty = false;
|
||||
private readonly ValidHandle allowUpdate = new();
|
||||
public override void OnAwake()
|
||||
{
|
||||
OnCosmeticsChanged();
|
||||
|
||||
if (_health is not null)
|
||||
_health.OnSetAlive += SetDirty;
|
||||
|
||||
if (_override is not null)
|
||||
_override.OnOverride += SetDirty;
|
||||
|
||||
if (_cosmeticService is not null)
|
||||
_cosmeticService.OnCosmeticsChanged += OnCosmeticsChanged;
|
||||
|
||||
destroyCancellationToken.Register(() =>
|
||||
{
|
||||
if (_cosmeticService is not null)
|
||||
_cosmeticService.OnCosmeticsChanged -= OnCosmeticsChanged;
|
||||
});
|
||||
|
||||
allowUpdate.AddElement(this);
|
||||
}
|
||||
public override void OnLateUpdate(float deltaTime)
|
||||
{
|
||||
base.OnLateUpdate(deltaTime);
|
||||
if (
|
||||
destroyCancellationToken.IsCancellationRequested
|
||||
|| !isDirty
|
||||
|| !_intervalUpdate.AllowUpdateWithoutReset
|
||||
|| allowUpdate.Allow is false
|
||||
) return;
|
||||
isDirty = false;
|
||||
EnsureConf();
|
||||
}
|
||||
[BIT]
|
||||
private void OnCosmeticsChanged()
|
||||
{
|
||||
allowUpdate.SetDisableElements(this);
|
||||
colliders = Array.Empty<Collider>();
|
||||
rigidbodies = Array.Empty<Rigidbody>();
|
||||
joints = Array.Empty<Joint>();
|
||||
|
||||
var rigidbodyList = new List<Rigidbody>();
|
||||
var collidersList = new List<Collider>();
|
||||
var jointList = new List<Joint>();
|
||||
foreach (var physicsComponent in GetComponentsInChildren<EntityPhysicsComponent>(true))
|
||||
{
|
||||
if(physicsComponent.Rigidbody)
|
||||
rigidbodyList.Add(physicsComponent.Rigidbody);
|
||||
if(physicsComponent.Collider)
|
||||
collidersList.Add(physicsComponent.Collider);
|
||||
if (physicsComponent.Joint)
|
||||
jointList.Add(physicsComponent.Joint);
|
||||
}
|
||||
colliders = collidersList.ToArray();
|
||||
rigidbodies = rigidbodyList.ToArray();
|
||||
joints = jointList.ToArray();
|
||||
|
||||
_jointXMotions.Clear();
|
||||
_jointYMotions.Clear();
|
||||
_jointZMotions.Clear();
|
||||
_jointAngularXMotions.Clear();
|
||||
_jointAngularYMotions.Clear();
|
||||
_jointAngularZMotions.Clear();
|
||||
foreach (var x in joints)
|
||||
{
|
||||
switch (x)
|
||||
{
|
||||
case ConfigurableJoint configurableJoint:
|
||||
_jointXMotions.Add(configurableJoint, configurableJoint.xMotion);
|
||||
_jointYMotions.Add(configurableJoint, configurableJoint.yMotion);
|
||||
_jointZMotions.Add(configurableJoint, configurableJoint.zMotion);
|
||||
_jointAngularXMotions.Add(configurableJoint, configurableJoint.angularXMotion);
|
||||
_jointAngularYMotions.Add(configurableJoint, configurableJoint.angularYMotion);
|
||||
_jointAngularZMotions.Add(configurableJoint, configurableJoint.angularZMotion);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rigidbody = animator.GetBoneTransform(HumanBodyBones.Hips)?.GetComponent<Rigidbody>();
|
||||
EnsureConf();
|
||||
isDirty = false;
|
||||
allowUpdate.RemoveDisableElements(this);
|
||||
}
|
||||
private void SetDirty(bool any) => SetDirty();
|
||||
private void SetDirty()
|
||||
{
|
||||
_intervalUpdate.Reset();
|
||||
isDirty = true;
|
||||
}
|
||||
private void EnsureConf()
|
||||
{
|
||||
var allow = (_health, _override) switch
|
||||
{
|
||||
(not null,not null)=>_health.IsAlive || _override.IsOvering,
|
||||
(not null,null)=>_health.IsAlive,
|
||||
(null,not null)=>_override.IsOvering,
|
||||
_=>true,
|
||||
};
|
||||
if (animator)
|
||||
{
|
||||
animator.enabled = allow;
|
||||
}
|
||||
try
|
||||
{
|
||||
foreach (var x in rigidbodies)
|
||||
{
|
||||
try
|
||||
{
|
||||
x.isKinematic= allow;
|
||||
x.gameObject.SetActive(!allow);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
}
|
||||
foreach (var x in colliders)
|
||||
{
|
||||
x.enabled = !allow;
|
||||
}
|
||||
|
||||
OnSetPhysics?.Invoke(!allow);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.LogException(e);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var joint in joints)
|
||||
{
|
||||
switch (joint)
|
||||
{
|
||||
case ConfigurableJoint configurableJoint:
|
||||
configurableJoint.xMotion = allow ? _jointXMotions[joint] : ConfigurableJointMotion.Free;
|
||||
configurableJoint.yMotion = allow ? _jointYMotions[joint] : ConfigurableJointMotion.Free;
|
||||
configurableJoint.zMotion = allow ? _jointZMotions[joint] : ConfigurableJointMotion.Free;
|
||||
configurableJoint.angularXMotion =
|
||||
allow ? _jointAngularXMotions[joint] : ConfigurableJointMotion.Free;
|
||||
configurableJoint.angularYMotion =
|
||||
allow ? _jointAngularYMotions[joint] : ConfigurableJointMotion.Free;
|
||||
configurableJoint.angularZMotion =
|
||||
allow ? _jointAngularZMotions[joint] : ConfigurableJointMotion.Free;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public Vector3 Center => rigidbody.worldCenterOfMass;
|
||||
public bool IsPhysics { get; private set; }
|
||||
public Vector3 Velocity
|
||||
{
|
||||
get => rigidbody ? rigidbody.velocity : default;
|
||||
set
|
||||
{
|
||||
foreach (var x in rigidbodies)
|
||||
{
|
||||
x.velocity = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public Action<bool> OnSetPhysics { get; set; }
|
||||
public void AddForce(Vector3 force, ForceMode mode = ForceMode.Force)
|
||||
{
|
||||
foreach (var x in rigidbodies)
|
||||
{
|
||||
x.AddForce(force, mode);
|
||||
}
|
||||
}
|
||||
public void AddTorque(Vector3 torque, ForceMode mode = ForceMode.Force)
|
||||
{
|
||||
foreach (var x in rigidbodies)
|
||||
{
|
||||
x.AddTorque(torque, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using BITKit;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
namespace BITFALL.Entities
|
||||
{
|
||||
public class EntityPhysicsComponent : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private new Collider collider;
|
||||
[SerializeField] private new Rigidbody rigidbody;
|
||||
[SerializeField] private Joint joint;
|
||||
public Collider Collider => collider;
|
||||
public Rigidbody Rigidbody => rigidbody;
|
||||
public Joint Joint => joint;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[BIT]
|
||||
private void SetUp()
|
||||
{
|
||||
collider = GetComponent<Collider>();
|
||||
rigidbody = GetComponent<Rigidbody>();
|
||||
joint = GetComponent<Joint>();
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
@@ -15,7 +15,6 @@ namespace BITFALL.Entities.Transition
|
||||
public sealed class EntityDamageTransition : EntityBehavior
|
||||
{
|
||||
[SerializeField] private List<EntityHitbox> damageParts;
|
||||
[SerializeField] private SkinnedMeshRenderer _skinnedMeshRenderer;
|
||||
[SerializeField, ReadOnly] private int currentThreshold;
|
||||
[SerializeField] private Entity newEntity;
|
||||
[SerializeField] private int initialThreshold;
|
||||
|
Reference in New Issue
Block a user