This commit is contained in:
CortexCore
2024-03-29 00:58:24 +08:00
parent 967ad8eacf
commit 05315ef4a8
232 changed files with 53368 additions and 8539 deletions

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}
}
}
}
}
}

View File

@@ -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;
}
}
}
}
}
}

View File

@@ -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);
}

View File

@@ -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();
}
}
}

View File

@@ -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;

View File

@@ -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))
{

View File

@@ -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);

View File

@@ -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))

View File

@@ -7,7 +7,8 @@
"GUID:0a8b74b3309f0cc44bdd9a796253baef",
"GUID:d525ad6bd40672747bde77962f1c401e",
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
"GUID:d8b63aba1907145bea998dd612889d6b"
"GUID:d8b63aba1907145bea998dd612889d6b",
"GUID:7efac18f239530141802fb139776f333"
],
"includePlatforms": [],
"excludePlatforms": [],

View File

@@ -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":

View File

@@ -19,6 +19,7 @@ namespace BITFALL.Movement.MotionBased
[Inject] private IEntityOverride _override;
[Inject] private IHealth _health;
private string lastAnimationName;
public override void OnStart()

View File

@@ -75,6 +75,8 @@ namespace BITFALL.Movement.MotionBased
_override.OnOverride += OnOverride;
_isAnimatorRoot = animancerComponent.Animator.transform == transform;
TransitionState<Walk>();
}
private void OnSetAlive(bool obj)

View File

@@ -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
}

View 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);
}
}
}
}

View File

@@ -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
}
}

View File

@@ -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;