Upload from upload_mods.ps1
This commit is contained in:
8
KFAttached/Animation/DebugScripts.meta
Normal file
8
KFAttached/Animation/DebugScripts.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e258bfeacfa28e49abe1c883f258a8b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimatorActionIndexDebug : StateMachineBehaviour
|
||||
{
|
||||
public override void OnStateMachineEnter(Animator animator, int stateMachinePathHash)
|
||||
{
|
||||
Log.Out($"StateMachine enter, Animator action index: {animator.GetInteger("ExecutingActionIndex")}");
|
||||
}
|
||||
|
||||
public override void OnStateMachineExit(Animator animator, int stateMachinePathHash)
|
||||
{
|
||||
Log.Out($"StateMachine exit, Animator action index: {animator.GetInteger("ExecutingActionIndex")}");
|
||||
}
|
||||
|
||||
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
Log.Out($"State entered!");
|
||||
}
|
||||
|
||||
public override void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
if (animator.GetBool("WeaponFire"))
|
||||
{
|
||||
Log.Out($"OnStateMove: Fire trigger set, Animator action index: {animator.GetInteger("ExecutingActionIndex")}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
if (animator.GetBool("WeaponFire"))
|
||||
{
|
||||
Log.Out($"OnStateUpdate: Fire trigger set, Animator action index: {animator.GetInteger("ExecutingActionIndex")}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c436ffdfb304ce144a66f57ef3e43bc4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
KFAttached/Animation/MonoBehaviours.meta
Normal file
8
KFAttached/Animation/MonoBehaviours.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90da1ffd0de481442b66207ea3c9263a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
using UnityEngine;
|
||||
|
||||
[AddComponentMenu("KFAttachments/Binding Helpers/Animation Aim Recoil References")]
|
||||
public class AnimationAimRecoilReferences : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private Transform[] aimRecoilTargets;
|
||||
private Vector3[] initialPositions;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (aimRecoilTargets != null)
|
||||
{
|
||||
initialPositions = new Vector3[aimRecoilTargets.Length];
|
||||
for (int i = 0; i < aimRecoilTargets.Length; i++)
|
||||
{
|
||||
initialPositions[i] = aimRecoilTargets[i].localPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Rollback()
|
||||
{
|
||||
if (aimRecoilTargets != null)
|
||||
{
|
||||
for (int i = 0; i < aimRecoilTargets.Length; i++)
|
||||
{
|
||||
aimRecoilTargets[i].localPosition = initialPositions[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ca4c020de5e68b4ca9902d948462df5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
212
KFAttached/Animation/MonoBehaviours/AnimationDelayRender.cs
Normal file
212
KFAttached/Animation/MonoBehaviours/AnimationDelayRender.cs
Normal file
@@ -0,0 +1,212 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
#if NotEditor
|
||||
using UniLinq;
|
||||
#else
|
||||
using System.Linq;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
using UnityEngine.Jobs;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
|
||||
[AddComponentMenu("")]
|
||||
public class AnimationDelayRender : MonoBehaviour
|
||||
{
|
||||
#if NotEditor
|
||||
[Serializable]
|
||||
public class TransformTargets
|
||||
{
|
||||
public Transform target;
|
||||
public bool includeChildren;
|
||||
}
|
||||
|
||||
public struct TransformLocalData
|
||||
{
|
||||
public Vector3 localPosition;
|
||||
public Quaternion localRotation;
|
||||
public Vector3 localScale;
|
||||
|
||||
public TransformLocalData(Vector3 localPosition, Quaternion localRotation, Vector3 localScale)
|
||||
{
|
||||
this.localPosition = localPosition;
|
||||
this.localRotation = localRotation;
|
||||
this.localScale = localScale;
|
||||
}
|
||||
}
|
||||
|
||||
private struct TransformRestoreJobs : IJobParallelForTransform
|
||||
{
|
||||
public NativeArray<TransformLocalData> data;
|
||||
public void Execute(int index, TransformAccess transform)
|
||||
{
|
||||
if (transform.isValid)
|
||||
{
|
||||
transform.SetLocalPositionAndRotation(data[index].localPosition, data[index].localRotation);
|
||||
transform.localScale = data[index].localScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct TransformRestoreAndSaveJobs : IJobParallelForTransform
|
||||
{
|
||||
public NativeArray<TransformLocalData> data;
|
||||
public void Execute(int index, TransformAccess transform)
|
||||
{
|
||||
if (transform.isValid)
|
||||
{
|
||||
TransformLocalData targetData = new TransformLocalData(transform.localPosition, transform.localRotation, transform.localScale);
|
||||
transform.SetLocalPositionAndRotation(data[index].localPosition, data[index].localRotation);
|
||||
transform.localScale = data[index].localScale;
|
||||
data[index] = targetData;
|
||||
}
|
||||
}
|
||||
}
|
||||
[NonSerialized]
|
||||
private Transform[] delayTargets;
|
||||
|
||||
private TransformLocalData[] posTargets;
|
||||
private EntityPlayerLocal player;
|
||||
|
||||
private NativeArray<TransformLocalData> data;
|
||||
TransformAccessArray transArr;
|
||||
private JobHandle restoreJob, restoreAndSaveJob;
|
||||
private bool dataInitialized = false;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
#if NotEditor
|
||||
player = GameManager.Instance?.World?.GetPrimaryPlayer();
|
||||
if (player == null)
|
||||
{
|
||||
Destroy(this);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
internal void InitializeTarget()
|
||||
{
|
||||
var delayTargetsSet = new HashSet<Transform>();
|
||||
foreach (Transform child in transform.GetComponentsInChildren<Transform>(true).Skip(1))
|
||||
{
|
||||
delayTargetsSet.Add(child);
|
||||
}
|
||||
delayTargets = delayTargetsSet.ToArray();
|
||||
posTargets = new TransformLocalData[delayTargets.Length];
|
||||
ClearNative();
|
||||
data = new NativeArray<TransformLocalData>(delayTargets.Length, Allocator.Persistent, NativeArrayOptions.ClearMemory);
|
||||
transArr = new TransformAccessArray(delayTargets);
|
||||
}
|
||||
|
||||
private void InitializeData()
|
||||
{
|
||||
for (int i = 0; i < delayTargets.Length; i++)
|
||||
{
|
||||
Transform target = delayTargets[i];
|
||||
if (target)
|
||||
{
|
||||
data[i] = new TransformLocalData(target.localPosition, target.localRotation, target.localScale);
|
||||
}
|
||||
}
|
||||
dataInitialized = true;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
InitializeTarget();
|
||||
player.playerCamera?.gameObject.GetOrAddComponent<AnimationDelayRenderReference>().targets.Add(this);
|
||||
//var preAnimatorUpdateJob = new TransformRestoreJobs
|
||||
//{
|
||||
// data = data
|
||||
//};
|
||||
//restoreJob = preAnimatorUpdateJob.Schedule(transArr);
|
||||
StartCoroutine(EndOfFrameCo());
|
||||
Log.Out($"Delay render target count: {delayTargets.Length}");
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
ClearNative();
|
||||
player.playerCamera?.gameObject.GetOrAddComponent<AnimationDelayRenderReference>().targets.Remove(this);
|
||||
StopAllCoroutines();
|
||||
dataInitialized = false;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
//for (int i = 0; i < delayTargets.Length; i++)
|
||||
//{
|
||||
// Transform target = delayTargets[i];
|
||||
// if (target)
|
||||
// {
|
||||
// target.localPosition = posTargets[i].localPosition;
|
||||
// target.localRotation = posTargets[i].localRotation;
|
||||
// target.localScale = posTargets[i].localScale;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// delayTargets[i] = null;
|
||||
// }
|
||||
//}
|
||||
restoreJob.Complete();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (!dataInitialized)
|
||||
return;
|
||||
var postAnimationUpdateJob = new TransformRestoreAndSaveJobs
|
||||
{
|
||||
data = data
|
||||
};
|
||||
restoreAndSaveJob = postAnimationUpdateJob.Schedule(transArr);
|
||||
//for (int i = 0; i < delayTargets.Length; i++)
|
||||
//{
|
||||
// Transform target = delayTargets[i];
|
||||
// if (target)
|
||||
// {
|
||||
// TransformLocalData targetData = new TransformLocalData(target.localPosition, target.localRotation, target.localScale);
|
||||
// target.localPosition = posTargets[i].localPosition;
|
||||
// target.localRotation = posTargets[i].localRotation;
|
||||
// target.localScale = posTargets[i].localScale;
|
||||
// posTargets[i] = targetData;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// delayTargets[i] = null;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
internal void PreCullCallback()
|
||||
{
|
||||
restoreAndSaveJob.Complete();
|
||||
}
|
||||
|
||||
private IEnumerator EndOfFrameCo()
|
||||
{
|
||||
yield return null;
|
||||
InitializeData();
|
||||
while (true)
|
||||
{
|
||||
yield return new WaitForEndOfFrame();
|
||||
var eofUpdateJob = new TransformRestoreJobs { data = data };
|
||||
restoreJob = eofUpdateJob.Schedule(transArr);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearNative()
|
||||
{
|
||||
if (data.IsCreated)
|
||||
{
|
||||
data.Dispose();
|
||||
}
|
||||
if (transArr.isCreated)
|
||||
{
|
||||
transArr.Dispose();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ba593a40bea2734a8fb4ea26a7c290e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
[AddComponentMenu("")]
|
||||
internal class AnimationDelayRenderReference : MonoBehaviour
|
||||
{
|
||||
#if NotEditor
|
||||
internal HashSet<AnimationDelayRender> targets = new HashSet<AnimationDelayRender>();
|
||||
private void OnPreCull()
|
||||
{
|
||||
if (targets.Count > 0)
|
||||
{
|
||||
foreach (var target in targets)
|
||||
{
|
||||
target.PreCullCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfa24b0d9ec212f4eb1f00580cfb4212
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
31
KFAttached/Animation/MonoBehaviours/AnimationFiringEvents.cs
Normal file
31
KFAttached/Animation/MonoBehaviours/AnimationFiringEvents.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimationFiringEvents : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private ParticleSystem[] mainParticles;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (mainParticles == null)
|
||||
return;
|
||||
foreach (var ps in mainParticles)
|
||||
{
|
||||
ps.gameObject.SetActive(true);
|
||||
var emission = ps.emission;
|
||||
emission.enabled = false;
|
||||
ps.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
|
||||
var main = ps.main;
|
||||
main.loop = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Fire(int index)
|
||||
{
|
||||
if (mainParticles == null || index < 0 || index >= mainParticles.Length)
|
||||
return;
|
||||
GameObject root = mainParticles[index].gameObject;
|
||||
root.BroadcastMessage("OnEnable", SendMessageOptions.DontRequireReceiver);
|
||||
mainParticles[index].Emit(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2a71dc0034e159458026e1103e44c62
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
381
KFAttached/Animation/MonoBehaviours/AnimationGraphBuilder.cs
Normal file
381
KFAttached/Animation/MonoBehaviours/AnimationGraphBuilder.cs
Normal file
@@ -0,0 +1,381 @@
|
||||
#if NotEditor
|
||||
#endif
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations;
|
||||
using UnityEngine.Playables;
|
||||
|
||||
[AddComponentMenu("")]
|
||||
public class AnimationGraphBuilder : MonoBehaviour
|
||||
{
|
||||
public enum ParamInWrapper
|
||||
{
|
||||
None,
|
||||
Vanilla,
|
||||
Weapon,
|
||||
Attachments,
|
||||
Both
|
||||
}
|
||||
private Animator animator;
|
||||
private RuntimeAnimatorController vanillaRuntimeController;
|
||||
private Avatar vanillaAvatar;
|
||||
private PlayableGraph graph;
|
||||
private AnimationLayerMixerPlayable mixer;
|
||||
private AnimatorControllerPlayable weaponControllerPlayable;
|
||||
private AnimatorControllerPlayable vanillaControllerPlayable;
|
||||
private Avatar weaponAvatar;
|
||||
private AvatarMask weaponMask;
|
||||
private bool isFpv;
|
||||
private bool isLocalPlayer = true;
|
||||
private readonly List<MonoBehaviour> graphRelatedBehaviours = new List<MonoBehaviour>();
|
||||
private AnimatorControllerParameter[] parameters;
|
||||
private readonly Dictionary<int, ParamInWrapper> paramMapping = new Dictionary<int, ParamInWrapper>();
|
||||
private readonly Dictionary<string, ParamInWrapper> paramMappingDebug = new Dictionary<string, ParamInWrapper>();
|
||||
//private Animator[] childAnimators = Array.Empty<Animator>();
|
||||
|
||||
public bool HasWeaponOverride => graph.IsValid();
|
||||
//public AnimatorControllerPlayable VanillaPlayable => vanillaControllerPlayable;
|
||||
//public AnimatorControllerPlayable WeaponPlayable => weaponControllerPlayable;
|
||||
public AnimatorControllerParameter[] Parameters => parameters;
|
||||
private AnimationTargetsAbs CurrentTarget { get; set; }
|
||||
public IAnimatorWrapper VanillaWrapper { get; private set; }
|
||||
public IAnimatorWrapper WeaponWrapper { get; private set; }
|
||||
public AttachmentWrapper AttachmentWrapper { get; private set; }
|
||||
public static IAnimatorWrapper DummyWrapper { get; } = new AnimatorWrapper(null);
|
||||
#if NotEditor
|
||||
public EntityPlayer Player { get; private set; }
|
||||
#endif
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
isFpv = transform.name == "baseRigFP";
|
||||
animator = GetComponent<Animator>();
|
||||
animator.logWarnings = false;
|
||||
VanillaWrapper = new AnimatorWrapper(animator);
|
||||
WeaponWrapper = new AnimatorWrapper(null);
|
||||
parameters = animator.parameters;
|
||||
UpdateParamMapping();
|
||||
vanillaAvatar = animator.avatar;
|
||||
#if NotEditor
|
||||
vanillaRuntimeController = isFpv ? SDCSUtils.FPAnimController : SDCSUtils.TPAnimController;
|
||||
isLocalPlayer = (Player = GetComponentInParent<EntityPlayer>()) is EntityPlayerLocal;
|
||||
#else
|
||||
vanillaRuntimeController = animator.runtimeAnimatorController;
|
||||
#endif
|
||||
}
|
||||
|
||||
private void UpdateParamMapping()
|
||||
{
|
||||
paramMapping.Clear();
|
||||
paramMappingDebug.Clear();
|
||||
var paramList = new List<AnimatorControllerParameter>();
|
||||
paramList.AddRange(animator.parameters);
|
||||
for (int i = 0; i < VanillaWrapper.GetParameterCount(); i++)
|
||||
{
|
||||
paramMapping.Add(VanillaWrapper.GetParameter(i).nameHash, ParamInWrapper.Vanilla);
|
||||
paramMappingDebug.Add(VanillaWrapper.GetParameter(i).name, ParamInWrapper.Vanilla);
|
||||
}
|
||||
if (WeaponWrapper != null && WeaponWrapper.IsValid)
|
||||
{
|
||||
for (int i = 0; i < WeaponWrapper.GetParameterCount(); i++)
|
||||
{
|
||||
var param = WeaponWrapper.GetParameter(i);
|
||||
if (paramMapping.ContainsKey(param.nameHash))
|
||||
{
|
||||
paramMapping[param.nameHash] = ParamInWrapper.Both;
|
||||
paramMappingDebug[param.name] = ParamInWrapper.Both;
|
||||
}
|
||||
else
|
||||
{
|
||||
paramMapping.Add(param.nameHash, ParamInWrapper.Weapon);
|
||||
paramMappingDebug.Add(param.name, ParamInWrapper.Weapon);
|
||||
paramList.Add(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (AttachmentWrapper != null && AttachmentWrapper.IsValid)
|
||||
{
|
||||
foreach (var animator in AttachmentWrapper.animators)
|
||||
{
|
||||
for (int i = 0; i < animator.parameterCount; i++)
|
||||
{
|
||||
var param = animator.GetParameter(i);
|
||||
if (!paramMapping.ContainsKey(param.nameHash))
|
||||
{
|
||||
paramMapping[param.nameHash] = ParamInWrapper.Attachments;
|
||||
paramList.Add(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parameters = paramList.ToArray();
|
||||
}
|
||||
|
||||
public ParamInWrapper GetWrapperRoleByParamHash(int nameHash)
|
||||
{
|
||||
if (paramMapping.TryGetValue(nameHash, out var role))
|
||||
return role;
|
||||
return ParamInWrapper.None;
|
||||
}
|
||||
|
||||
public ParamInWrapper GetWrapperRoleByParamName(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name) || !paramMapping.TryGetValue(Animator.StringToHash(name), out var role))
|
||||
return ParamInWrapper.None;
|
||||
return role;
|
||||
}
|
||||
|
||||
public ParamInWrapper GetWrapperRoleByParam(AnimatorControllerParameter param)
|
||||
{
|
||||
if (param == null || !paramMapping.TryGetValue(param.nameHash, out var role))
|
||||
return ParamInWrapper.None;
|
||||
return role;
|
||||
}
|
||||
|
||||
public void SetChildFloat(int nameHash, float value)
|
||||
{
|
||||
if (AttachmentWrapper != null && AttachmentWrapper.IsValid)
|
||||
{
|
||||
AttachmentWrapper.SetFloat(nameHash, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetChildBool(int nameHash, bool value)
|
||||
{
|
||||
if (AttachmentWrapper != null && AttachmentWrapper.IsValid)
|
||||
{
|
||||
AttachmentWrapper.SetBool(nameHash, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetChildInteger(int nameHash, int value)
|
||||
{
|
||||
if (AttachmentWrapper != null && AttachmentWrapper.IsValid)
|
||||
{
|
||||
AttachmentWrapper.SetInteger(nameHash, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetChildTrigger(int nameHash)
|
||||
{
|
||||
if (AttachmentWrapper != null && AttachmentWrapper.IsValid)
|
||||
{
|
||||
AttachmentWrapper.SetTrigger(nameHash);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetChildTrigger(int nameHash)
|
||||
{
|
||||
if (AttachmentWrapper != null && AttachmentWrapper.IsValid)
|
||||
{
|
||||
AttachmentWrapper.ResetTrigger(nameHash);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitGraph()
|
||||
{
|
||||
animator.runtimeAnimatorController = null;
|
||||
if (graph.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
graph = PlayableGraph.Create();
|
||||
mixer = AnimationLayerMixerPlayable.Create(graph, 2);
|
||||
var output = AnimationPlayableOutput.Create(graph, "output", animator);
|
||||
output.SetSourcePlayable(mixer);
|
||||
InitVanilla();
|
||||
graph.Play();
|
||||
}
|
||||
|
||||
private void InitVanilla()
|
||||
{
|
||||
vanillaControllerPlayable = AnimatorControllerPlayable.Create(graph, vanillaRuntimeController);
|
||||
mixer.ConnectInput(0, vanillaControllerPlayable, 0, isFpv ? 0 : 1.0f);
|
||||
mixer.SetLayerAdditive(0, false);
|
||||
}
|
||||
|
||||
public void InitWeapon(Transform weaponRoot, RuntimeAnimatorController weaponRuntimeController, AvatarMask weaponMask)
|
||||
{
|
||||
InitGraph();
|
||||
InitBehaviours(weaponRoot);
|
||||
weaponAvatar = AvatarBuilder.BuildGenericAvatar(gameObject, "Origin");
|
||||
animator.avatar = weaponAvatar;
|
||||
weaponControllerPlayable = AnimatorControllerPlayable.Create(graph, weaponRuntimeController);
|
||||
mixer.ConnectInput(1, weaponControllerPlayable, 0, 1.0f);
|
||||
mixer.SetLayerAdditive(1, false);
|
||||
if (weaponMask)
|
||||
{
|
||||
mixer.SetLayerMaskFromAvatarMask(1, weaponMask);
|
||||
}
|
||||
this.weaponMask = weaponMask;
|
||||
}
|
||||
|
||||
private void DestroyGraph()
|
||||
{
|
||||
CleanupBehaviours();
|
||||
weaponMask = null;
|
||||
if (graph.IsValid())
|
||||
{
|
||||
graph.Destroy();
|
||||
}
|
||||
if (animator)
|
||||
{
|
||||
animator.runtimeAnimatorController = vanillaRuntimeController;
|
||||
animator.avatar = vanillaAvatar;
|
||||
}
|
||||
}
|
||||
|
||||
private void DestroyWeapon()
|
||||
{
|
||||
CleanupBehaviours();
|
||||
weaponMask = null;
|
||||
if (weaponControllerPlayable.IsValid())
|
||||
{
|
||||
mixer.DisconnectInput(1);
|
||||
weaponControllerPlayable.Destroy();
|
||||
}
|
||||
animator.avatar = vanillaAvatar;
|
||||
Destroy(weaponAvatar);
|
||||
animator.runtimeAnimatorController = vanillaRuntimeController;
|
||||
}
|
||||
|
||||
public void SetCurrentTarget(AnimationTargetsAbs target)
|
||||
{
|
||||
if (CurrentTarget == target)
|
||||
{
|
||||
UpdateChildAnimatorArray(target);
|
||||
return;
|
||||
}
|
||||
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
#if NotEditor
|
||||
bool wasCrouching = VanillaWrapper != null && VanillaWrapper.IsValid && VanillaWrapper.GetBool(AvatarController.isCrouchingHash);
|
||||
#endif
|
||||
//var rb = animator.transform.AddMissingComponent<RigBuilder>();
|
||||
//rb.enabled = false;
|
||||
if (CurrentTarget)
|
||||
{
|
||||
CurrentTarget.SetEnabled(false);
|
||||
}
|
||||
|
||||
bool useGraph = target && (target is PlayGraphTargets || (target.ItemTpv && !isFpv));
|
||||
if (HasWeaponOverride)
|
||||
{
|
||||
if (useGraph)
|
||||
{
|
||||
DestroyWeapon();
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyGraph();
|
||||
}
|
||||
}
|
||||
|
||||
CurrentTarget = target;
|
||||
if (target)
|
||||
{
|
||||
target.SetEnabled(true);
|
||||
}
|
||||
// Log.Out($"\n#=================Rebuild Start");
|
||||
//#if NotEditor
|
||||
// Log.Out($"Remaining RigLayers on build:\n{string.Join("\n", rb.layers.Select(layer => layer.name))}");
|
||||
//#endif
|
||||
// animator.UnbindAllSceneHandles();
|
||||
// animator.UnbindAllStreamHandles();
|
||||
// rb.enabled = true;
|
||||
// animator.Rebind();
|
||||
// Log.Out($"#=================Rebuild Finish\n");
|
||||
animator.WriteDefaultValues();
|
||||
|
||||
if (useGraph)
|
||||
{
|
||||
VanillaWrapper = new PlayableWrapper(vanillaControllerPlayable);
|
||||
WeaponWrapper = new PlayableWrapper(weaponControllerPlayable);
|
||||
}
|
||||
else
|
||||
{
|
||||
VanillaWrapper = new AnimatorWrapper(animator);
|
||||
if (target)
|
||||
{
|
||||
WeaponWrapper = new AnimatorWrapper(target.ItemAnimator);
|
||||
}
|
||||
else
|
||||
{
|
||||
WeaponWrapper = DummyWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateChildAnimatorArray(target);
|
||||
UpdateParamMapping();
|
||||
#if NotEditor
|
||||
animator.SetWrappedBool(AvatarController.isCrouchingHash, wasCrouching);
|
||||
if (isFpv)
|
||||
{
|
||||
VanillaWrapper.Play("idle", 0, 0f);
|
||||
VanillaWrapper.SetInteger(AvatarController.weaponHoldTypeHash, -1);
|
||||
}
|
||||
if (wasCrouching && !isFpv && VanillaWrapper.GetLayerCount() > 4)
|
||||
{
|
||||
VanillaWrapper.Play("2HGeneric", 4, 0);
|
||||
}
|
||||
#endif
|
||||
sw.Stop();
|
||||
Log.Out($"changing animation target to {(target ? target.name : "null")} took {sw.ElapsedMilliseconds}");
|
||||
}
|
||||
|
||||
private void UpdateChildAnimatorArray(AnimationTargetsAbs target)
|
||||
{
|
||||
Animator[] childAnimators;
|
||||
if (target && target.ItemCurrentOrDefault)
|
||||
{
|
||||
List<Animator> animators = new List<Animator>();
|
||||
foreach (Transform trans in target.ItemCurrentOrDefault)
|
||||
{
|
||||
animators.AddRange(trans.GetComponentsInChildren<Animator>());
|
||||
}
|
||||
if (target.ItemAnimator)
|
||||
{
|
||||
animators.Remove(target.ItemAnimator);
|
||||
}
|
||||
childAnimators = animators.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
childAnimators = Array.Empty<Animator>();
|
||||
}
|
||||
AttachmentWrapper = new AttachmentWrapper(childAnimators);
|
||||
}
|
||||
|
||||
private void InitBehaviours(Transform weaponRoot)
|
||||
{
|
||||
foreach (var scripts in weaponRoot.GetComponents<IPlayableGraphRelated>())
|
||||
{
|
||||
var behaviour = scripts.Init(transform, isLocalPlayer);
|
||||
if (behaviour)
|
||||
{
|
||||
graphRelatedBehaviours.Add(behaviour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CleanupBehaviours()
|
||||
{
|
||||
foreach (var behaviour in graphRelatedBehaviours)
|
||||
{
|
||||
if (behaviour)
|
||||
{
|
||||
(behaviour as IPlayableGraphRelated)?.Disable(transform);
|
||||
}
|
||||
}
|
||||
graphRelatedBehaviours.Clear();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
SetCurrentTarget(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43f465f7371212e4f8ce8241007afd67
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
using UnityEngine;
|
||||
|
||||
public abstract class AnimationProceduralRecoildAbs : MonoBehaviour
|
||||
{
|
||||
public abstract void AddRecoil(Vector3 positionMultiplier, Vector3 rotationMultiplier);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ee261f617ba41e469d725bd8f2cb3c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
163
KFAttached/Animation/MonoBehaviours/AnimationRandomRecoil.cs
Normal file
163
KFAttached/Animation/MonoBehaviours/AnimationRandomRecoil.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using DG.Tweening;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
[AddComponentMenu("KFAttachments/Binding Helpers/Animation Random Recoil")]
|
||||
public class AnimationRandomRecoil : AnimationProceduralRecoildAbs, IPlayableGraphRelated
|
||||
#if UNITY_EDITOR
|
||||
, ISerializationCallbackReceiver
|
||||
#endif
|
||||
{
|
||||
[Header("Targets")]
|
||||
[SerializeField] private Transform target;
|
||||
[SerializeField, HideInInspector] private string targetName;
|
||||
[SerializeField] private Transform pivot;
|
||||
[SerializeField, HideInInspector] private string pivotName;
|
||||
[Header("Rotation")]
|
||||
//[SerializeField] private Vector3 minRotation = new Vector3(-5, -2, -2);
|
||||
//[SerializeField] private Vector3 maxRotation = new Vector3(0, 2, 2);
|
||||
[SerializeField] private Vector3 randomRotationMin = new Vector3(-3, -1, -1);
|
||||
[SerializeField] private Vector3 randomRotationMax = new Vector3(-1, 1, 1);
|
||||
[Header("Kickback")]
|
||||
//[SerializeField] private Vector3 minKickback = new Vector3(0, 0, -0.05f);
|
||||
//[SerializeField] private Vector3 maxKickback = new Vector3(0, 0, 0);
|
||||
[SerializeField] private Vector3 randomKickbackMin = new Vector3(0, 0, -0.025f);
|
||||
[SerializeField] private Vector3 randomKickbackMax = new Vector3(0, 0, -0.01f);
|
||||
[Header("Recoil")]
|
||||
[SerializeField, Range(0, 0.1f)] private float tweenInDuration = 0.04f;
|
||||
[SerializeField, Range(0, 5)] private float tweenOutDuration = 1.5f;
|
||||
[Header("Return")]
|
||||
[SerializeField, Range(1, 5)] private float elasticAmplitude = 1f;
|
||||
[SerializeField, Range(0, 1)] private float elasticPeriod = 0.5f;
|
||||
|
||||
private Vector3 targetRotation = Vector3.zero;
|
||||
private Vector3 targetPosition = Vector3.zero;
|
||||
private Vector3 currentRotation = Vector3.zero;
|
||||
private Vector3 currentPosition = Vector3.zero;
|
||||
private Sequence seq;
|
||||
//private bool isTweeningIn = true;
|
||||
|
||||
public override void AddRecoil(Vector3 positionMultiplier, Vector3 rotationMultiplier)
|
||||
{
|
||||
if (target && pivot)
|
||||
{
|
||||
targetPosition = Vector3.Scale(KFExtensions.Random(randomKickbackMin, randomKickbackMax), positionMultiplier);
|
||||
targetRotation = Vector3.Scale(KFExtensions.Random(randomRotationMin, randomRotationMax), rotationMultiplier);
|
||||
GameObject targetObj = target.gameObject;
|
||||
RecreateSeq();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ResetSeq();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
ResetSeq();
|
||||
}
|
||||
|
||||
private void ResetSeq()
|
||||
{
|
||||
seq?.Rewind(false);
|
||||
if (target)
|
||||
{
|
||||
target.localEulerAngles = Vector3.zero;
|
||||
target.localPosition = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void RecreateSeq()
|
||||
{
|
||||
currentPosition = Vector3.zero;
|
||||
currentRotation = Vector3.zero;
|
||||
seq?.Kill(false);
|
||||
seq = DOTween.Sequence()
|
||||
//.InsertCallback(0, () => isTweeningIn = true)
|
||||
.Insert(0, DOTween.To(() => currentRotation, (rot) => currentRotation = rot, targetRotation, tweenInDuration).SetEase(Ease.OutCubic))
|
||||
.Insert(0, DOTween.To(() => currentPosition, (pos) => currentPosition = pos, targetPosition, tweenInDuration).SetEase(Ease.OutCubic))
|
||||
//.InsertCallback(tweenInDuration, () => isTweeningIn = false)
|
||||
.Insert(tweenInDuration, DOTween.To(() => currentRotation, (rot) => currentRotation = rot, Vector3.zero, tweenOutDuration).SetEase(Ease.OutElastic, elasticAmplitude, elasticPeriod))
|
||||
.Insert(tweenInDuration, DOTween.To(() => currentPosition, (rot) => currentPosition = rot, Vector3.zero, tweenOutDuration).SetEase(Ease.OutElastic, elasticAmplitude, elasticPeriod))
|
||||
.OnUpdate(UpdateTransform)
|
||||
.SetAutoKill(true)
|
||||
.SetRecyclable();
|
||||
}
|
||||
|
||||
private void UpdateTransform()
|
||||
{
|
||||
if (target)
|
||||
{
|
||||
target.localEulerAngles = Vector3.zero;
|
||||
target.localPosition = Vector3.zero;
|
||||
target.RotateAroundPivot(pivot, currentRotation);
|
||||
target.localPosition += currentPosition;
|
||||
}
|
||||
|
||||
//if (!isTweeningIn)
|
||||
//{
|
||||
// targetRotation = currentRotation;
|
||||
// targetPosition = currentPosition;
|
||||
//}
|
||||
}
|
||||
|
||||
public MonoBehaviour Init(Transform playerAnimatorTrans, bool isLocalPlayer)
|
||||
{
|
||||
if (isLocalPlayer)
|
||||
{
|
||||
var copy = playerAnimatorTrans.AddMissingComponent<AnimationRandomRecoil>();
|
||||
copy.enabled = true;
|
||||
if (target)
|
||||
{
|
||||
copy.target = this.target;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy.target = playerAnimatorTrans.FindInAllChildren(targetName);
|
||||
}
|
||||
if (pivot)
|
||||
{
|
||||
copy.pivot = pivot;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy.pivot = playerAnimatorTrans.FindInAllChildren(pivotName);
|
||||
}
|
||||
copy.randomRotationMin = this.randomRotationMin;
|
||||
copy.randomRotationMax = this.randomRotationMax;
|
||||
copy.randomKickbackMin = this.randomKickbackMin;
|
||||
copy.randomKickbackMax = this.randomKickbackMax;
|
||||
copy.tweenInDuration = this.tweenInDuration;
|
||||
copy.tweenOutDuration = this.tweenOutDuration;
|
||||
copy.elasticAmplitude = this.elasticAmplitude;
|
||||
copy.elasticPeriod = this.elasticPeriod;
|
||||
return copy;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Disable(Transform playerAnimatorTrans)
|
||||
{
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
if (target)
|
||||
{
|
||||
targetName = target.name;
|
||||
}
|
||||
if (pivot)
|
||||
{
|
||||
pivotName = pivot.name;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd683a2a71b72f04f88532f056986903
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
97
KFAttached/Animation/MonoBehaviours/AnimationRandomSound.cs
Normal file
97
KFAttached/Animation/MonoBehaviours/AnimationRandomSound.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
[AddComponentMenu("KFAttachments/Utils/Animation Random Sound")]
|
||||
public class AnimationRandomSound : MonoBehaviour, ISerializationCallbackReceiver
|
||||
{
|
||||
[SerializeField]
|
||||
public List<AudioSourceGroup> audioSourcesEditor;
|
||||
[NonSerialized]
|
||||
private List<AudioSourceGroup> audioSources;
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private List<string> list_groupnames;
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private List<AudioClip> list_clips;
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private List<AudioSource> list_sources;
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private List<int> list_clip_indices;
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private int serializedCount = 0;
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
audioSources = new List<AudioSourceGroup>();
|
||||
for (int i = 0; i < serializedCount; i++)
|
||||
{
|
||||
int index = (i == 0 ? 0 : list_clip_indices[i - 1]);
|
||||
int count = list_clip_indices[i] - index;
|
||||
audioSources.Add(new AudioSourceGroup()
|
||||
{
|
||||
groupName = list_groupnames[i],
|
||||
clips = list_clips.Skip(index).Take(count).ToArray(),
|
||||
source = list_sources[i],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
if (audioSourcesEditor != null && audioSourcesEditor.Count > 0)
|
||||
{
|
||||
serializedCount = 0;
|
||||
list_groupnames = new List<string>();
|
||||
list_clips = new List<AudioClip>();
|
||||
list_clip_indices = new List<int>();
|
||||
list_sources = new List<AudioSource>();
|
||||
for (int i = 0; i < audioSourcesEditor.Count; i++)
|
||||
{
|
||||
list_groupnames.Add(audioSourcesEditor[i].groupName);
|
||||
list_clips.AddRange(audioSourcesEditor[i].clips);
|
||||
list_sources.Add(audioSourcesEditor[i].source);
|
||||
list_clip_indices.Add(list_clips.Count);
|
||||
serializedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayRandomClip(string group)
|
||||
{
|
||||
if (audioSources == null)
|
||||
return;
|
||||
|
||||
//#if NotEditor
|
||||
// Log.Out($"play random clip {group}, groups: {string.Join("| ", audioSources.Select(g => g.groupName + $"clips: {string.Join(", ", g.clips.Select(c => c.name))}"))}");
|
||||
//#endif
|
||||
AudioSourceGroup asg = null;
|
||||
foreach (var audioSourceGroup in audioSources)
|
||||
{
|
||||
if (audioSourceGroup.groupName == group)
|
||||
{
|
||||
asg = audioSourceGroup;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (asg == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int random = Random.Range(0, asg.clips.Length);
|
||||
//asg.source.clip = asg.clips[random];
|
||||
asg.source.PlayOneShot(asg.clips[random]);
|
||||
//#if NotEditor
|
||||
// Log.Out($"play clip {asg.clips[random].name}");
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 517d2eb7e1af8a740a6f8ae7cb775f5f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
356
KFAttached/Animation/MonoBehaviours/AnimationReloadEvents.cs
Normal file
356
KFAttached/Animation/MonoBehaviours/AnimationReloadEvents.cs
Normal file
@@ -0,0 +1,356 @@
|
||||
#if NotEditor
|
||||
using KFCommonUtilityLib;
|
||||
|
||||
#endif
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
[AddComponentMenu("KFAttachments/Utils/Animation Reload Events")]
|
||||
public class AnimationReloadEvents : MonoBehaviour, IPlayableGraphRelated
|
||||
{
|
||||
private void Awake()
|
||||
{
|
||||
animator = GetComponent<Animator>();
|
||||
#if NotEditor
|
||||
player = GetComponentInParent<EntityAlive>();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void OnReloadFinish()
|
||||
{
|
||||
OnReloadAmmo();
|
||||
OnReloadEnd();
|
||||
}
|
||||
|
||||
public void OnReloadAmmo()
|
||||
{
|
||||
#if NotEditor
|
||||
if (actionData == null || !actionData.isReloading)
|
||||
{
|
||||
#if DEBUG
|
||||
Log.Out($"ANIMATION RELOAD EVENT NOT RELOADING : {actionData?.invData.item.Name ?? "null"}");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (!actionData.isReloadCancelled)
|
||||
{
|
||||
player.MinEventContext.ItemActionData = actionData;
|
||||
ItemValue item = ItemClass.GetItem(actionRanged.MagazineItemNames[actionData.invData.itemValue.SelectedAmmoTypeIndex], false);
|
||||
int magSize = actionRanged.GetMaxAmmoCount(actionData);
|
||||
actionData.reloadAmount = GetAmmoCountToReload(player, item, magSize);
|
||||
if (actionData.reloadAmount > 0)
|
||||
{
|
||||
actionData.invData.itemValue.Meta = Utils.FastMin(actionData.invData.itemValue.Meta + actionData.reloadAmount, magSize);
|
||||
if (actionData.invData.item.Properties.Values[ItemClass.PropSoundIdle] != null)
|
||||
{
|
||||
actionData.invData.holdingEntitySoundID = -1;
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
Log.Out($"ANIMATION RELOAD EVENT AMMO : {actionData.invData.item.Name}");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public void OnReloadEnd()
|
||||
{
|
||||
StopAllCoroutines();
|
||||
animator.SetWrappedBool(Animator.StringToHash("Reload"), false);
|
||||
animator.SetWrappedBool(Animator.StringToHash("IsReloading"), false);
|
||||
animator.speed = 1f;
|
||||
#if NotEditor
|
||||
cancelReloadCo = null;
|
||||
if (actionData == null || !actionData.isReloading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
actionData.isReloading = false;
|
||||
actionData.isWeaponReloading = false;
|
||||
actionData.invData.holdingEntity.MinEventContext.ItemActionData = actionData;
|
||||
actionData.invData.holdingEntity.FireEvent(MinEventTypes.onReloadStop, true);
|
||||
actionData.invData.holdingEntity.OnReloadEnd();
|
||||
actionData.invData.holdingEntity.inventory.CallOnToolbeltChangedInternal();
|
||||
AnimationAmmoUpdateState.SetAmmoCountForEntity(actionData.invData.holdingEntity, actionData.invData.slotIdx);
|
||||
actionData.isReloadCancelled = false;
|
||||
actionData.isWeaponReloadCancelled = false;
|
||||
actionData.isChangingAmmoType = false;
|
||||
if (actionData is IModuleContainerFor<ActionModuleMultiBarrel.MultiBarrelData> dataModule)
|
||||
{
|
||||
dataModule.Instance.SetCurrentBarrel(actionData.invData.itemValue.Meta);
|
||||
}
|
||||
#if DEBUG
|
||||
Log.Out($"ANIMATION RELOAD EVENT FINISHED : {actionData.invData.item.Name}");
|
||||
#endif
|
||||
actionData = null;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void OnPartialReloadEnd()
|
||||
{
|
||||
#if NotEditor
|
||||
if (actionData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
player.MinEventContext.ItemActionData = actionData;
|
||||
ItemValue ammo = ItemClass.GetItem(actionRanged.MagazineItemNames[actionData.invData.itemValue.SelectedAmmoTypeIndex], false);
|
||||
int magSize = (int)EffectManager.GetValue(PassiveEffects.MagazineSize, actionData.invData.itemValue, (float)actionRanged.BulletsPerMagazine, player);
|
||||
int partialReloadCount = (int)EffectManager.GetValue(CustomEnums.PartialReloadCount, actionData.invData.itemValue, 1, player);
|
||||
actionData.reloadAmount = GetPartialReloadCount(player, ammo, magSize, partialReloadCount);
|
||||
if (actionData.reloadAmount > 0)
|
||||
{
|
||||
actionData.invData.itemValue.Meta = Utils.FastMin(actionData.invData.itemValue.Meta + actionData.reloadAmount, magSize);
|
||||
if (actionData.invData.item.Properties.Values[ItemClass.PropSoundIdle] != null)
|
||||
{
|
||||
actionData.invData.holdingEntitySoundID = -1;
|
||||
}
|
||||
}
|
||||
AnimationAmmoUpdateState.SetAmmoCountForEntity(actionData.invData.holdingEntity, actionData.invData.slotIdx);
|
||||
|
||||
if (actionData.isReloadCancelled || actionData.isWeaponReloadCancelled || actionData.invData.itemValue.Meta >= magSize || player.GetItemCount(ammo) <= 0)
|
||||
{
|
||||
Log.Out("Partial reload finished");
|
||||
animator.SetWrappedBool(Animator.StringToHash("IsReloading"), false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NotEditor
|
||||
//public bool ReloadUpdatedThisFrame => reloadUpdatedThisFrame;
|
||||
//private bool reloadUpdatedThisFrame = false;
|
||||
//internal void OnReloadUpdate()
|
||||
//{
|
||||
// reloadUpdatedThisFrame = true;
|
||||
//}
|
||||
|
||||
//private void OnAnimatorMove()
|
||||
//{
|
||||
// if (actionData != null)
|
||||
// {
|
||||
// //if (actionData.isReloading && !reloadUpdatedThisFrame)
|
||||
// //{
|
||||
// // Log.Warning("Animator not sending update msg this frame, reloading is cancelled!");
|
||||
// // actionData.isReloadCancelled = true;
|
||||
// // OnReloadFinish();
|
||||
// //}
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// //Log.Warning("actionData is null!");
|
||||
// }
|
||||
// reloadUpdatedThisFrame = false;
|
||||
//}
|
||||
|
||||
public void OnReloadStart(int actionIndex)
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
player = GetComponentInParent<EntityAlive>();
|
||||
}
|
||||
actionData = player.inventory.holdingItemData.actionData[actionIndex] as ItemActionRanged.ItemActionDataRanged;
|
||||
actionRanged = (ItemActionRanged)player.inventory.holdingItem.Actions[actionIndex];
|
||||
if (actionData == null || actionData.isReloading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionData.invData.item.Properties.Values[ItemClass.PropSoundIdle] != null && actionData.invData.holdingEntitySoundID >= 0)
|
||||
{
|
||||
Audio.Manager.Stop(actionData.invData.holdingEntity.entityId, actionData.invData.item.Properties.Values[ItemClass.PropSoundIdle]);
|
||||
}
|
||||
actionData.wasAiming = actionData.invData.holdingEntity.AimingGun;
|
||||
if (actionData.invData.holdingEntity.AimingGun && actionData.invData.item.Actions[1] is ItemActionZoom)
|
||||
{
|
||||
actionData.invData.holdingEntity.inventory.Execute(1, false, null);
|
||||
actionData.invData.holdingEntity.inventory.Execute(1, true, null);
|
||||
}
|
||||
if (animator.GetCurrentAnimatorClipInfo(0).Length != 0 && animator.GetCurrentAnimatorClipInfo(0)[0].clip.events.Length == 0)
|
||||
{
|
||||
if (actionRanged.SoundReload != null)
|
||||
{
|
||||
player.PlayOneShot(actionRanged.SoundReload.Value, false);
|
||||
}
|
||||
}
|
||||
else if (animator.GetNextAnimatorClipInfo(0).Length != 0 && animator.GetNextAnimatorClipInfo(0)[0].clip.events.Length == 0 && actionRanged.SoundReload != null)
|
||||
{
|
||||
player.PlayOneShot(actionRanged.SoundReload.Value, false);
|
||||
}
|
||||
|
||||
ItemValue itemValue = actionData.invData.itemValue;
|
||||
actionData.invData.holdingEntity.MinEventContext.ItemActionData = actionData;
|
||||
int magSize = (int)EffectManager.GetValue(PassiveEffects.MagazineSize, itemValue, actionRanged.BulletsPerMagazine, actionData.invData.holdingEntity);
|
||||
ItemActionLauncher itemActionLauncher = actionRanged as ItemActionLauncher;
|
||||
if (itemActionLauncher != null && itemValue.Meta < magSize)
|
||||
{
|
||||
ItemValue ammoValue = ItemClass.GetItem(actionRanged.MagazineItemNames[itemValue.SelectedAmmoTypeIndex], false);
|
||||
if (ConsoleCmdReloadLog.LogInfo)
|
||||
Log.Out($"loading ammo {ammoValue.ItemClass.Name}");
|
||||
ItemActionLauncher.ItemActionDataLauncher itemActionDataLauncher = actionData as ItemActionLauncher.ItemActionDataLauncher;
|
||||
if (itemActionDataLauncher.isChangingAmmoType)
|
||||
{
|
||||
if (ConsoleCmdReloadLog.LogInfo)
|
||||
Log.Out($"is changing ammo type {itemActionDataLauncher.isChangingAmmoType}");
|
||||
itemActionLauncher.DeleteProjectiles(actionData);
|
||||
itemActionDataLauncher.isChangingAmmoType = false;
|
||||
}
|
||||
int projectileCount = 1;
|
||||
if (!actionData.invData.holdingEntity.isEntityRemote)
|
||||
{
|
||||
projectileCount = (itemActionLauncher.HasInfiniteAmmo(actionData) ? magSize : GetAmmoCount(actionData.invData.holdingEntity, ammoValue, magSize));
|
||||
projectileCount *= getProjectileCount(itemActionDataLauncher);
|
||||
}
|
||||
int times = 1;
|
||||
IModuleContainerFor<ActionModuleMultiBarrel.MultiBarrelData> dataModule = actionData as IModuleContainerFor<ActionModuleMultiBarrel.MultiBarrelData>;
|
||||
if (dataModule != null && dataModule.Instance.oneRoundMultishot)
|
||||
{
|
||||
times = dataModule.Instance.roundsPerShot;
|
||||
}
|
||||
for (int j = itemActionDataLauncher.projectileInstance.Count; j < projectileCount; j++)
|
||||
{
|
||||
for (int i = 0; i < times; i++)
|
||||
{
|
||||
if (dataModule != null)
|
||||
{
|
||||
itemActionDataLauncher.projectileJoint = dataModule.Instance.projectileJoints[i];
|
||||
}
|
||||
itemActionDataLauncher.projectileInstance.Add(itemActionLauncher.instantiateProjectile(actionData, Vector3.zero));
|
||||
}
|
||||
}
|
||||
}
|
||||
actionData.isReloading = true;
|
||||
actionData.isWeaponReloading = true;
|
||||
actionData.invData.holdingEntity.FireEvent(MinEventTypes.onReloadStart, true);
|
||||
#if DEBUG
|
||||
Log.Out($"ANIMATION EVENT RELOAD START : {actionData.invData.item.Name}");
|
||||
#endif
|
||||
}
|
||||
|
||||
private Coroutine cancelReloadCo = null;
|
||||
|
||||
public void DelayForceCancelReload(float delay)
|
||||
{
|
||||
if (cancelReloadCo == null)
|
||||
cancelReloadCo = StartCoroutine(ForceCancelReloadCo(delay));
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (animator)
|
||||
{
|
||||
OnReloadEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator ForceCancelReloadCo(float delay)
|
||||
{
|
||||
yield return new WaitForSecondsRealtime(delay);
|
||||
if (actionData != null && (actionData.isReloading || actionData.isWeaponReloading) && (actionData.isReloadCancelled || actionData.isWeaponReloadCancelled))
|
||||
OnReloadEnd();
|
||||
cancelReloadCo = null;
|
||||
}
|
||||
|
||||
public int GetAmmoCountToReload(EntityAlive ea, ItemValue ammo, int modifiedMagazineSize)
|
||||
{
|
||||
int meta = actionData.invData.itemValue.Meta;
|
||||
int target = modifiedMagazineSize - meta;
|
||||
if (actionRanged.HasInfiniteAmmo(actionData))
|
||||
{
|
||||
if (actionRanged.AmmoIsPerMagazine)
|
||||
{
|
||||
return modifiedMagazineSize;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
if (ea.bag.GetItemCount(ammo, -1, -1, true) > 0)
|
||||
{
|
||||
if (actionRanged.AmmoIsPerMagazine)
|
||||
{
|
||||
return modifiedMagazineSize * ea.bag.DecItem(ammo, 1, false, null);
|
||||
}
|
||||
res = ea.bag.DecItem(ammo, target, false, null);
|
||||
if (res == target)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (actionRanged.AmmoIsPerMagazine)
|
||||
{
|
||||
return modifiedMagazineSize * ea.inventory.DecItem(ammo, 1, false, null);
|
||||
}
|
||||
|
||||
if (ea.inventory.GetItemCount(ammo, false, -1, -1, true) <= 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
return res + actionData.invData.holdingEntity.inventory.DecItem(ammo, target - res, false, null);
|
||||
}
|
||||
|
||||
public int GetPartialReloadCount(EntityAlive ea, ItemValue ammo, int modifiedMagazineSize, int partialReloadCount)
|
||||
{
|
||||
int meta = actionData.invData.itemValue.Meta;
|
||||
int target = Mathf.Min(partialReloadCount, modifiedMagazineSize - meta);
|
||||
if (actionRanged.HasInfiniteAmmo(actionData))
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
if (ea.bag.GetItemCount(ammo) > 0)
|
||||
{
|
||||
res = ea.bag.DecItem(ammo, target);
|
||||
if (res == target)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (ea.inventory.GetItemCount(ammo) <= 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
return res + actionData.invData.holdingEntity.inventory.DecItem(ammo, target - res);
|
||||
}
|
||||
|
||||
public int GetAmmoCount(EntityAlive ea, ItemValue ammo, int modifiedMagazineSize)
|
||||
{
|
||||
return Mathf.Min(ea.bag.GetItemCount(ammo, -1, -1, true) + ea.inventory.GetItemCount(ammo, false, -1, -1, true) + actionData.invData.itemValue.Meta, modifiedMagazineSize);
|
||||
}
|
||||
|
||||
public int getProjectileCount(ItemActionData _data)
|
||||
{
|
||||
int rps = 1;
|
||||
ItemInventoryData invD = _data != null ? _data.invData : null;
|
||||
if (invD != null)
|
||||
{
|
||||
ItemClass item = invD.itemValue != null ? invD.itemValue.ItemClass : null;
|
||||
rps = (int)EffectManager.GetValue(PassiveEffects.RoundRayCount, invD.itemValue, rps, invD.holdingEntity);
|
||||
}
|
||||
return rps > 0 ? rps : 1;
|
||||
}
|
||||
|
||||
public EntityAlive player;
|
||||
public ItemActionRanged.ItemActionDataRanged actionData;
|
||||
public ItemActionRanged actionRanged;
|
||||
#endif
|
||||
private Animator animator;
|
||||
|
||||
public MonoBehaviour Init(Transform playerAnimatorTrans, bool isLocalPlayer)
|
||||
{
|
||||
var copy = playerAnimatorTrans.AddMissingComponent<AnimationReloadEvents>();
|
||||
if (copy)
|
||||
{
|
||||
copy.enabled = true;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
public void Disable(Transform playerAnimatorTrans)
|
||||
{
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c245bc8d9e873ae40ac1f6078f9611c8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimationSmokeParticle : MonoBehaviour
|
||||
{
|
||||
private ParticleSystem ps;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (!TryGetComponent(out ps))
|
||||
Destroy(this);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ps.Clear(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 173c51f67c407a94388cc82dddafc06f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
KFAttached/Animation/MonoBehaviours/AnimatorWrapper.meta
Normal file
8
KFAttached/Animation/MonoBehaviours/AnimatorWrapper.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74718732aa3d8274fb470008c5d9e819
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,131 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimatorWrapper : IAnimatorWrapper
|
||||
{
|
||||
private Animator animator;
|
||||
|
||||
public bool IsValid => animator;
|
||||
|
||||
public AnimatorWrapper(Animator animator) => this.animator = animator;
|
||||
|
||||
public void CrossFade(string stateName, float transitionDuration) => animator.CrossFade(stateName, transitionDuration);
|
||||
|
||||
public void CrossFade(string stateName, float transitionDuration, int layer) => animator.CrossFade(stateName, transitionDuration, layer);
|
||||
|
||||
public void CrossFade(string stateName, float transitionDuration, int layer, float normalizedTime) => animator.CrossFade(stateName, transitionDuration, layer, normalizedTime);
|
||||
|
||||
public void CrossFade(int stateNameHash, float transitionDuration) => animator.CrossFade(stateNameHash, transitionDuration);
|
||||
|
||||
public void CrossFade(int stateNameHash, float transitionDuration, int layer) => animator.CrossFade(stateNameHash, transitionDuration, layer);
|
||||
|
||||
public void CrossFade(int stateNameHash, float transitionDuration, int layer, float normalizedTime) => animator.CrossFade(stateNameHash, transitionDuration, layer, normalizedTime);
|
||||
|
||||
public void CrossFadeInFixedTime(string stateName, float transitionDuration) => animator.CrossFadeInFixedTime(stateName, transitionDuration);
|
||||
|
||||
public void CrossFadeInFixedTime(string stateName, float transitionDuration, int layer) => animator.CrossFadeInFixedTime(stateName, transitionDuration, layer);
|
||||
|
||||
public void CrossFadeInFixedTime(string stateName, float transitionDuration, int layer, float fixedTime) => animator.CrossFadeInFixedTime(stateName, transitionDuration, layer, fixedTime);
|
||||
|
||||
public void CrossFadeInFixedTime(int stateNameHash, float transitionDuration) => animator.CrossFadeInFixedTime(stateNameHash, transitionDuration);
|
||||
|
||||
public void CrossFadeInFixedTime(int stateNameHash, float transitionDuration, int layer) => animator.CrossFadeInFixedTime(stateNameHash, transitionDuration, layer);
|
||||
|
||||
public void CrossFadeInFixedTime(int stateNameHash, float transitionDuration, int layer, float fixedTime) => animator.CrossFadeInFixedTime(stateNameHash, transitionDuration, layer, fixedTime);
|
||||
|
||||
public AnimatorTransitionInfo GetAnimatorTransitionInfo(int layerIndex) => animator.GetAnimatorTransitionInfo(layerIndex);
|
||||
|
||||
public bool GetBool(string name) => animator.GetBool(name);
|
||||
|
||||
public bool GetBool(int id) => animator.GetBool(id);
|
||||
|
||||
public AnimatorClipInfo[] GetCurrentAnimatorClipInfo(int layerIndex) => animator.GetCurrentAnimatorClipInfo(layerIndex);
|
||||
|
||||
public void GetCurrentAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips) => animator.GetCurrentAnimatorClipInfo(layerIndex, clips);
|
||||
|
||||
public int GetCurrentAnimatorClipInfoCount(int layerIndex) => animator.GetCurrentAnimatorClipInfoCount(layerIndex);
|
||||
|
||||
public AnimatorStateInfo GetCurrentAnimatorStateInfo(int layerIndex) => animator.GetCurrentAnimatorStateInfo(layerIndex);
|
||||
|
||||
public float GetFloat(string name) => animator.GetFloat(name);
|
||||
|
||||
public float GetFloat(int id) => animator.GetFloat(id);
|
||||
|
||||
public int GetInteger(string name) => animator.GetInteger(name);
|
||||
|
||||
public int GetInteger(int id) => animator.GetInteger(id);
|
||||
|
||||
public int GetLayerCount() => animator.layerCount;
|
||||
|
||||
public int GetLayerIndex(string layerName) => animator.GetLayerIndex(layerName);
|
||||
|
||||
public string GetLayerName(int layerIndex) => animator.GetLayerName(layerIndex);
|
||||
|
||||
public float GetLayerWeight(int layerIndex) => animator.GetLayerWeight(layerIndex);
|
||||
|
||||
public void GetNextAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips) => animator.GetNextAnimatorClipInfo(layerIndex, clips);
|
||||
|
||||
public AnimatorClipInfo[] GetNextAnimatorClipInfo(int layerIndex) => animator.GetNextAnimatorClipInfo(layerIndex);
|
||||
|
||||
public int GetNextAnimatorClipInfoCount(int layerIndex) => animator.GetNextAnimatorClipInfoCount(layerIndex);
|
||||
|
||||
public AnimatorStateInfo GetNextAnimatorStateInfo(int layerIndex) => animator.GetNextAnimatorStateInfo(layerIndex);
|
||||
|
||||
public AnimatorControllerParameter GetParameter(int index) => animator.GetParameter(index);
|
||||
|
||||
public int GetParameterCount() => animator.parameterCount;
|
||||
|
||||
public bool HasState(int layerIndex, int stateID) => animator.HasState(layerIndex, stateID);
|
||||
|
||||
public bool IsInTransition(int layerIndex) => animator.IsInTransition(layerIndex);
|
||||
|
||||
public bool IsParameterControlledByCurve(string name) => animator.IsParameterControlledByCurve(name);
|
||||
|
||||
public bool IsParameterControlledByCurve(int id) => animator.IsParameterControlledByCurve(id);
|
||||
|
||||
public void Play(string stateName) => animator.Play(stateName);
|
||||
|
||||
public void Play(string stateName, int layer) => animator.Play(stateName, layer);
|
||||
|
||||
public void Play(string stateName, int layer, float normalizedTime) => animator.Play(stateName, layer, normalizedTime);
|
||||
|
||||
public void Play(int stateNameHash) => animator.Play(stateNameHash);
|
||||
|
||||
public void Play(int stateNameHash, int layer) => animator.Play(stateNameHash, layer);
|
||||
|
||||
public void Play(int stateNameHash, int layer, float normalizedTime) => animator.Play(stateNameHash, layer, normalizedTime);
|
||||
|
||||
public void PlayInFixedTime(string stateName) => animator.PlayInFixedTime(stateName);
|
||||
|
||||
public void PlayInFixedTime(string stateName, int layer) => animator.PlayInFixedTime(stateName, layer);
|
||||
|
||||
public void PlayInFixedTime(string stateName, int layer, float fixedTime) => animator.PlayInFixedTime(stateName, layer, fixedTime);
|
||||
|
||||
public void PlayInFixedTime(int stateNameHash) => animator.PlayInFixedTime(stateNameHash);
|
||||
|
||||
public void PlayInFixedTime(int stateNameHash, int layer) => animator.PlayInFixedTime(stateNameHash, layer);
|
||||
|
||||
public void PlayInFixedTime(int stateNameHash, int layer, float fixedTime) => animator.PlayInFixedTime(stateNameHash, layer, fixedTime);
|
||||
|
||||
public void ResetTrigger(string name) => animator.ResetTrigger(name);
|
||||
|
||||
public void ResetTrigger(int id) => animator.ResetTrigger(id);
|
||||
|
||||
public void SetBool(string name, bool value) => animator.SetBool(name, value);
|
||||
|
||||
public void SetBool(int id, bool value) => animator.SetBool(id, value);
|
||||
|
||||
public void SetFloat(string name, float value) => animator.SetFloat(name, value);
|
||||
|
||||
public void SetFloat(int id, float value) => animator.SetFloat(id, value);
|
||||
|
||||
public void SetInteger(string name, int value) => animator.SetInteger(name, value);
|
||||
|
||||
public void SetInteger(int id, int value) => animator.SetInteger(id, value);
|
||||
|
||||
public void SetLayerWeight(int layerIndex, float weight) => animator.SetLayerWeight(layerIndex, weight);
|
||||
|
||||
public void SetTrigger(string name) => animator.SetTrigger(name);
|
||||
|
||||
public void SetTrigger(int id) => animator.SetTrigger(id);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 330523dd2a309f042a9aafdb565149c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,443 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
public class AttachmentWrapper : IAnimatorWrapper
|
||||
{
|
||||
public Animator[] animators;
|
||||
public AttachmentWrapper(Animator[] animators)
|
||||
{
|
||||
this.animators = animators;
|
||||
}
|
||||
|
||||
public bool IsValid => animators != null && animators.Length > 0;
|
||||
|
||||
public void CrossFade(string stateName, float transitionDuration)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFade(stateName, transitionDuration);
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossFade(string stateName, float transitionDuration, int layer)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFade(stateName, transitionDuration, layer);
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossFade(string stateName, float transitionDuration, int layer, float normalizedTime)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFade(stateName, transitionDuration, layer, normalizedTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossFade(int stateNameHash, float transitionDuration)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFade(stateNameHash, transitionDuration);
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossFade(int stateNameHash, float transitionDuration, int layer)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFade(stateNameHash, transitionDuration, layer);
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossFade(int stateNameHash, float transitionDuration, int layer, float normalizedTime)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFade(stateNameHash, transitionDuration, layer, normalizedTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossFadeInFixedTime(string stateName, float transitionDuration)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFadeInFixedTime(stateName, transitionDuration);
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossFadeInFixedTime(string stateName, float transitionDuration, int layer)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFadeInFixedTime(stateName, transitionDuration, layer);
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossFadeInFixedTime(string stateName, float transitionDuration, int layer, float fixedTime)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFadeInFixedTime(stateName, transitionDuration, layer, fixedTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossFadeInFixedTime(int stateNameHash, float transitionDuration)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFadeInFixedTime(stateNameHash, transitionDuration);
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossFadeInFixedTime(int stateNameHash, float transitionDuration, int layer)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFadeInFixedTime(stateNameHash, transitionDuration, layer);
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossFadeInFixedTime(int stateNameHash, float transitionDuration, int layer, float fixedTime)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.CrossFadeInFixedTime(stateNameHash, transitionDuration, layer, fixedTime);
|
||||
}
|
||||
}
|
||||
|
||||
public AnimatorTransitionInfo GetAnimatorTransitionInfo(int layerIndex)
|
||||
{
|
||||
return animators[0].GetAnimatorTransitionInfo(layerIndex);
|
||||
}
|
||||
|
||||
public bool GetBool(string name)
|
||||
{
|
||||
return GetBool(Animator.StringToHash(name));
|
||||
}
|
||||
|
||||
public bool GetBool(int id)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
if (animator.GetBool(id))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public AnimatorClipInfo[] GetCurrentAnimatorClipInfo(int layerIndex)
|
||||
{
|
||||
return animators[0].GetCurrentAnimatorClipInfo(layerIndex);
|
||||
}
|
||||
|
||||
public void GetCurrentAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips)
|
||||
{
|
||||
animators[0].GetCurrentAnimatorClipInfo(layerIndex, clips);
|
||||
}
|
||||
|
||||
public int GetCurrentAnimatorClipInfoCount(int layerIndex)
|
||||
{
|
||||
return animators[0].GetCurrentAnimatorClipInfoCount(layerIndex);
|
||||
}
|
||||
|
||||
public AnimatorStateInfo GetCurrentAnimatorStateInfo(int layerIndex)
|
||||
{
|
||||
return animators[0].GetCurrentAnimatorStateInfo(layerIndex);
|
||||
}
|
||||
|
||||
public float GetFloat(string name)
|
||||
{
|
||||
return GetFloat(Animator.StringToHash(name));
|
||||
}
|
||||
|
||||
public float GetFloat(int id)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
float value = animator.GetFloat(id);
|
||||
if (value != 0)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int GetInteger(string name)
|
||||
{
|
||||
return GetInteger(Animator.StringToHash(name));
|
||||
}
|
||||
|
||||
public int GetInteger(int id)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
int value = animator.GetInteger(id);
|
||||
if (value != 0)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int GetLayerCount()
|
||||
{
|
||||
return animators[0].layerCount;
|
||||
}
|
||||
|
||||
public int GetLayerIndex(string layerName)
|
||||
{
|
||||
return animators[0].GetLayerIndex(layerName);
|
||||
}
|
||||
|
||||
public string GetLayerName(int layerIndex)
|
||||
{
|
||||
return animators[0].GetLayerName(layerIndex);
|
||||
}
|
||||
|
||||
public float GetLayerWeight(int layerIndex)
|
||||
{
|
||||
return animators[0].GetLayerWeight(layerIndex);
|
||||
}
|
||||
|
||||
public void GetNextAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips)
|
||||
{
|
||||
animators[0].GetNextAnimatorClipInfo(layerIndex, clips);
|
||||
}
|
||||
|
||||
public AnimatorClipInfo[] GetNextAnimatorClipInfo(int layerIndex)
|
||||
{
|
||||
return animators[0].GetNextAnimatorClipInfo(layerIndex);
|
||||
}
|
||||
|
||||
public int GetNextAnimatorClipInfoCount(int layerIndex)
|
||||
{
|
||||
return animators[0].GetNextAnimatorClipInfoCount(layerIndex);
|
||||
}
|
||||
|
||||
public AnimatorStateInfo GetNextAnimatorStateInfo(int layerIndex)
|
||||
{
|
||||
return animators[0].GetNextAnimatorStateInfo(layerIndex);
|
||||
}
|
||||
|
||||
public AnimatorControllerParameter GetParameter(int index)
|
||||
{
|
||||
return animators[0].GetParameter(index);
|
||||
}
|
||||
|
||||
public int GetParameterCount()
|
||||
{
|
||||
return animators[0].parameterCount;
|
||||
}
|
||||
|
||||
public bool HasState(int layerIndex, int stateID)
|
||||
{
|
||||
return animators[0].HasState(layerIndex, stateID);
|
||||
}
|
||||
|
||||
public bool IsInTransition(int layerIndex)
|
||||
{
|
||||
return animators[0].IsInTransition(layerIndex);
|
||||
}
|
||||
|
||||
public bool IsParameterControlledByCurve(string name)
|
||||
{
|
||||
return animators[0].IsParameterControlledByCurve(name);
|
||||
}
|
||||
|
||||
public bool IsParameterControlledByCurve(int id)
|
||||
{
|
||||
return animators[0].IsParameterControlledByCurve(id);
|
||||
}
|
||||
|
||||
public void Play(string stateName)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.Play(stateName);
|
||||
}
|
||||
}
|
||||
|
||||
public void Play(string stateName, int layer)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.Play(stateName, layer);
|
||||
}
|
||||
}
|
||||
|
||||
public void Play(string stateName, int layer, float normalizedTime)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.Play(stateName, layer, normalizedTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void Play(int stateNameHash)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.Play(stateNameHash);
|
||||
}
|
||||
}
|
||||
|
||||
public void Play(int stateNameHash, int layer)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.Play(stateNameHash, layer);
|
||||
}
|
||||
}
|
||||
|
||||
public void Play(int stateNameHash, int layer, float normalizedTime)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.Play(stateNameHash, layer, normalizedTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayInFixedTime(string stateName)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.PlayInFixedTime(stateName);
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayInFixedTime(string stateName, int layer)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.PlayInFixedTime(stateName, layer);
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayInFixedTime(string stateName, int layer, float fixedTime)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.PlayInFixedTime(stateName, layer, fixedTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayInFixedTime(int stateNameHash)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.PlayInFixedTime(stateNameHash);
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayInFixedTime(int stateNameHash, int layer)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.PlayInFixedTime(stateNameHash, layer);
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayInFixedTime(int stateNameHash, int layer, float fixedTime)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.PlayInFixedTime(stateNameHash, layer, fixedTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetTrigger(string name)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.ResetTrigger(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetTrigger(int id)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.ResetTrigger(id);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBool(string name, bool value)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.SetBool(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBool(int id, bool value)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.SetBool(id, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFloat(string name, float value)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.SetFloat(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFloat(int id, float value)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.SetFloat(id, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetInteger(string name, int value)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.SetInteger(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetInteger(int id, int value)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.SetInteger(id, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLayerWeight(int layerIndex, float weight)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.SetLayerWeight(layerIndex, weight);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTrigger(string name)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.SetTrigger(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTrigger(int id)
|
||||
{
|
||||
foreach (var animator in animators)
|
||||
{
|
||||
animator.SetTrigger(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9aff1989baed1884fb65a80108d5ab68
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,92 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations;
|
||||
using UnityEngine.Playables;
|
||||
|
||||
public class PlayableWrapper : IAnimatorWrapper
|
||||
{
|
||||
private AnimatorControllerPlayable playable;
|
||||
|
||||
public PlayableWrapper(AnimatorControllerPlayable playable)
|
||||
{
|
||||
this.playable = playable;
|
||||
}
|
||||
|
||||
public bool IsValid => playable.IsValid();
|
||||
|
||||
public float GetFloat(string name) => playable.GetFloat(name);
|
||||
public float GetFloat(int id) => playable.GetFloat(id);
|
||||
public void SetFloat(string name, float value) => playable.SetFloat(name, value);
|
||||
public void SetFloat(int id, float value) => playable.SetFloat(id, value);
|
||||
|
||||
public bool GetBool(string name) => playable.GetBool(name);
|
||||
public bool GetBool(int id) => playable.GetBool(id);
|
||||
public void SetBool(string name, bool value) => playable.SetBool(name, value);
|
||||
public void SetBool(int id, bool value) => playable.SetBool(id, value);
|
||||
|
||||
public int GetInteger(string name) => playable.GetInteger(name);
|
||||
public int GetInteger(int id) => playable.GetInteger(id);
|
||||
public void SetInteger(string name, int value) => playable.SetInteger(name, value);
|
||||
public void SetInteger(int id, int value) => playable.SetInteger(id, value);
|
||||
|
||||
public void SetTrigger(string name) => playable.SetTrigger(name);
|
||||
public void SetTrigger(int id) => playable.SetTrigger(id);
|
||||
public void ResetTrigger(string name) => playable.ResetTrigger(name);
|
||||
public void ResetTrigger(int id) => playable.ResetTrigger(id);
|
||||
|
||||
public bool IsParameterControlledByCurve(string name) => playable.IsParameterControlledByCurve(name);
|
||||
public bool IsParameterControlledByCurve(int id) => playable.IsParameterControlledByCurve(id);
|
||||
|
||||
public int GetLayerCount() => playable.GetLayerCount();
|
||||
public string GetLayerName(int layerIndex) => playable.GetLayerName(layerIndex);
|
||||
public int GetLayerIndex(string layerName) => playable.GetLayerIndex(layerName);
|
||||
public float GetLayerWeight(int layerIndex) => playable.GetLayerWeight(layerIndex);
|
||||
public void SetLayerWeight(int layerIndex, float weight) => playable.SetLayerWeight(layerIndex, weight);
|
||||
|
||||
public AnimatorStateInfo GetCurrentAnimatorStateInfo(int layerIndex) => playable.GetCurrentAnimatorStateInfo(layerIndex);
|
||||
public AnimatorStateInfo GetNextAnimatorStateInfo(int layerIndex) => playable.GetNextAnimatorStateInfo(layerIndex);
|
||||
public AnimatorTransitionInfo GetAnimatorTransitionInfo(int layerIndex) => playable.GetAnimatorTransitionInfo(layerIndex);
|
||||
|
||||
public AnimatorClipInfo[] GetCurrentAnimatorClipInfo(int layerIndex) => playable.GetCurrentAnimatorClipInfo(layerIndex);
|
||||
public void GetCurrentAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips) => playable.GetCurrentAnimatorClipInfo(layerIndex, clips);
|
||||
public void GetNextAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips) => playable.GetNextAnimatorClipInfo(layerIndex, clips);
|
||||
public int GetCurrentAnimatorClipInfoCount(int layerIndex) => playable.GetCurrentAnimatorClipInfoCount(layerIndex);
|
||||
public int GetNextAnimatorClipInfoCount(int layerIndex) => playable.GetNextAnimatorClipInfoCount(layerIndex);
|
||||
public AnimatorClipInfo[] GetNextAnimatorClipInfo(int layerIndex) => playable.GetNextAnimatorClipInfo(layerIndex);
|
||||
|
||||
public bool IsInTransition(int layerIndex) => playable.IsInTransition(layerIndex);
|
||||
|
||||
public int GetParameterCount() => playable.GetParameterCount();
|
||||
public AnimatorControllerParameter GetParameter(int index) => playable.GetParameter(index);
|
||||
|
||||
public void CrossFadeInFixedTime(string stateName, float transitionDuration) => playable.CrossFadeInFixedTime(stateName, transitionDuration);
|
||||
public void CrossFadeInFixedTime(string stateName, float transitionDuration, int layer) => playable.CrossFadeInFixedTime(stateName, transitionDuration, layer);
|
||||
public void CrossFadeInFixedTime(string stateName, float transitionDuration, int layer, float fixedTime) => playable.CrossFadeInFixedTime(stateName, transitionDuration, layer, fixedTime);
|
||||
public void CrossFadeInFixedTime(int stateNameHash, float transitionDuration) => playable.CrossFadeInFixedTime(stateNameHash, transitionDuration);
|
||||
public void CrossFadeInFixedTime(int stateNameHash, float transitionDuration, int layer) => playable.CrossFadeInFixedTime(stateNameHash, transitionDuration, layer);
|
||||
public void CrossFadeInFixedTime(int stateNameHash, float transitionDuration, int layer, float fixedTime) => playable.CrossFadeInFixedTime(stateNameHash, transitionDuration, layer, fixedTime);
|
||||
|
||||
public void CrossFade(string stateName, float transitionDuration) => playable.CrossFade(stateName, transitionDuration);
|
||||
public void CrossFade(string stateName, float transitionDuration, int layer) => playable.CrossFade(stateName, transitionDuration, layer);
|
||||
public void CrossFade(string stateName, float transitionDuration, int layer, float normalizedTime) => playable.CrossFade(stateName, transitionDuration, layer, normalizedTime);
|
||||
public void CrossFade(int stateNameHash, float transitionDuration) => playable.CrossFade(stateNameHash, transitionDuration);
|
||||
public void CrossFade(int stateNameHash, float transitionDuration, int layer) => playable.CrossFade(stateNameHash, transitionDuration, layer);
|
||||
public void CrossFade(int stateNameHash, float transitionDuration, int layer, float normalizedTime) => playable.CrossFade(stateNameHash, transitionDuration, layer, normalizedTime);
|
||||
|
||||
public void PlayInFixedTime(string stateName) => playable.PlayInFixedTime(stateName);
|
||||
public void PlayInFixedTime(string stateName, int layer) => playable.PlayInFixedTime(stateName, layer);
|
||||
public void PlayInFixedTime(string stateName, int layer, float fixedTime) => playable.PlayInFixedTime(stateName, layer, fixedTime);
|
||||
public void PlayInFixedTime(int stateNameHash) => playable.PlayInFixedTime(stateNameHash);
|
||||
public void PlayInFixedTime(int stateNameHash, int layer) => playable.PlayInFixedTime(stateNameHash, layer);
|
||||
public void PlayInFixedTime(int stateNameHash, int layer, float fixedTime) => playable.PlayInFixedTime(stateNameHash, layer, fixedTime);
|
||||
|
||||
public void Play(string stateName) => playable.Play(stateName);
|
||||
public void Play(string stateName, int layer) => playable.Play(stateName, layer);
|
||||
public void Play(string stateName, int layer, float normalizedTime) => playable.Play(stateName, layer, normalizedTime);
|
||||
public void Play(int stateNameHash) => playable.Play(stateNameHash);
|
||||
public void Play(int stateNameHash, int layer) => playable.Play(stateNameHash, layer);
|
||||
public void Play(int stateNameHash, int layer, float normalizedTime) => playable.Play(stateNameHash, layer, normalizedTime);
|
||||
|
||||
public bool HasState(int layerIndex, int stateID) => playable.HasState(layerIndex, stateID);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af94698a131639a4ba070db09410d746
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
73
KFAttached/Animation/MonoBehaviours/IAnimatorWrapper.cs
Normal file
73
KFAttached/Animation/MonoBehaviours/IAnimatorWrapper.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations;
|
||||
using UnityEngine.Playables;
|
||||
|
||||
public interface IAnimatorWrapper
|
||||
{
|
||||
bool IsValid { get; }
|
||||
float GetFloat(string name);
|
||||
float GetFloat(int id);
|
||||
void SetFloat(string name, float value);
|
||||
void SetFloat(int id, float value);
|
||||
bool GetBool(string name);
|
||||
bool GetBool(int id);
|
||||
void SetBool(string name, bool value);
|
||||
void SetBool(int id, bool value);
|
||||
int GetInteger(string name);
|
||||
int GetInteger(int id);
|
||||
void SetInteger(string name, int value);
|
||||
void SetInteger(int id, int value);
|
||||
void SetTrigger(string name);
|
||||
void SetTrigger(int id);
|
||||
void ResetTrigger(string name);
|
||||
void ResetTrigger(int id);
|
||||
bool IsParameterControlledByCurve(string name);
|
||||
bool IsParameterControlledByCurve(int id);
|
||||
int GetLayerCount();
|
||||
string GetLayerName(int layerIndex);
|
||||
int GetLayerIndex(string layerName);
|
||||
float GetLayerWeight(int layerIndex);
|
||||
void SetLayerWeight(int layerIndex, float weight);
|
||||
AnimatorStateInfo GetCurrentAnimatorStateInfo(int layerIndex);
|
||||
AnimatorStateInfo GetNextAnimatorStateInfo(int layerIndex);
|
||||
AnimatorTransitionInfo GetAnimatorTransitionInfo(int layerIndex);
|
||||
AnimatorClipInfo[] GetCurrentAnimatorClipInfo(int layerIndex);
|
||||
void GetCurrentAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips);
|
||||
void GetNextAnimatorClipInfo(int layerIndex, List<AnimatorClipInfo> clips);
|
||||
int GetCurrentAnimatorClipInfoCount(int layerIndex);
|
||||
int GetNextAnimatorClipInfoCount(int layerIndex);
|
||||
AnimatorClipInfo[] GetNextAnimatorClipInfo(int layerIndex);
|
||||
bool IsInTransition(int layerIndex);
|
||||
int GetParameterCount();
|
||||
AnimatorControllerParameter GetParameter(int index);
|
||||
void CrossFadeInFixedTime(string stateName, float transitionDuration);
|
||||
void CrossFadeInFixedTime(string stateName, float transitionDuration, int layer);
|
||||
void CrossFadeInFixedTime(string stateName, float transitionDuration, int layer, float fixedTime);
|
||||
void CrossFadeInFixedTime(int stateNameHash, float transitionDuration);
|
||||
void CrossFadeInFixedTime(int stateNameHash, float transitionDuration, int layer);
|
||||
void CrossFadeInFixedTime(int stateNameHash, float transitionDuration, int layer, float fixedTime);
|
||||
void CrossFade(string stateName, float transitionDuration);
|
||||
void CrossFade(string stateName, float transitionDuration, int layer);
|
||||
void CrossFade(string stateName, float transitionDuration, int layer, float normalizedTime);
|
||||
void CrossFade(int stateNameHash, float transitionDuration);
|
||||
void CrossFade(int stateNameHash, float transitionDuration, int layer);
|
||||
void CrossFade(int stateNameHash, float transitionDuration, int layer, float normalizedTime);
|
||||
void PlayInFixedTime(string stateName);
|
||||
void PlayInFixedTime(string stateName, int layer);
|
||||
void PlayInFixedTime(string stateName, int layer, float fixedTime);
|
||||
void PlayInFixedTime(int stateNameHash);
|
||||
void PlayInFixedTime(int stateNameHash, int layer);
|
||||
void PlayInFixedTime(int stateNameHash, int layer, float fixedTime);
|
||||
void Play(string stateName);
|
||||
void Play(string stateName, int layer);
|
||||
void Play(string stateName, int layer, float normalizedTime);
|
||||
void Play(int stateNameHash);
|
||||
void Play(int stateNameHash, int layer);
|
||||
void Play(int stateNameHash, int layer, float normalizedTime);
|
||||
bool HasState(int layerIndex, int stateID);
|
||||
}
|
||||
11
KFAttached/Animation/MonoBehaviours/IAnimatorWrapper.cs.meta
Normal file
11
KFAttached/Animation/MonoBehaviours/IAnimatorWrapper.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b52da8de87636d42aa5130c88c5fe4d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
using UnityEngine;
|
||||
|
||||
public interface IPlayableGraphRelated
|
||||
{
|
||||
MonoBehaviour Init(Transform playerAnimatorTrans, bool isLocalPlayer);
|
||||
void Disable(Transform playerAnimatorTrans);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 952699e2d9986c94bb12291f3d5e948a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
123
KFAttached/Animation/MonoBehaviours/RigWeightOverTime.cs
Normal file
123
KFAttached/Animation/MonoBehaviours/RigWeightOverTime.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations.Rigging;
|
||||
|
||||
[AddComponentMenu("KFAttachments/Utils/Rig Weight Over Time")]
|
||||
public class RigWeightOverTime : MonoBehaviour
|
||||
{
|
||||
//[SerializeField]
|
||||
//private Transform source;
|
||||
//[SerializeField]
|
||||
//private Transform target;
|
||||
[SerializeReference]
|
||||
private Rig[] rigs;
|
||||
//[SerializeField]
|
||||
//private float distanceThreshold;
|
||||
//[SerializeField]
|
||||
//private float distanceMax;
|
||||
//private float distanceRange;
|
||||
|
||||
private (Coroutine co, bool active) copair;
|
||||
////[SerializeField]
|
||||
////private bool logDistance = false;
|
||||
|
||||
//private void Awake()
|
||||
//{
|
||||
// distanceRange = distanceMax - distanceThreshold;
|
||||
// if (distanceRange == 0)
|
||||
// {
|
||||
// throw new DivideByZeroException("Max distance is equal to threshold distance!");
|
||||
// }
|
||||
//}
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
if (rigs != null)
|
||||
{
|
||||
SetWeight(1);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
if (copair.co != null)
|
||||
{
|
||||
StopCoroutine(copair.co);
|
||||
}
|
||||
SetWeight(0);
|
||||
}
|
||||
|
||||
public void SetRigWeight(AnimationEvent ev)
|
||||
{
|
||||
if (copair.co != null)
|
||||
{
|
||||
StopCoroutine(copair.co);
|
||||
}
|
||||
bool active = Convert.ToBoolean(ev.intParameter);
|
||||
copair = (StartCoroutine(UpdateWeight(ev.floatParameter, active)), active);
|
||||
}
|
||||
|
||||
private IEnumerator UpdateWeight(float time, bool active)
|
||||
{
|
||||
if (rigs == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (time == 0)
|
||||
{
|
||||
SetWeight(active ? 1 : 0);
|
||||
yield break;
|
||||
}
|
||||
|
||||
float curTime = 0;
|
||||
while (curTime < time)
|
||||
{
|
||||
float ratio = curTime / time;
|
||||
float weight = Mathf.Lerp(0, 1, active ? ratio : (1 - ratio));
|
||||
SetWeight(weight);
|
||||
curTime += Time.deltaTime;
|
||||
Log.Out("Set weight: " + weight);
|
||||
yield return null;
|
||||
}
|
||||
SetWeight(active ? 1 : 0);
|
||||
}
|
||||
|
||||
public void SetWeight(float weight)
|
||||
{
|
||||
foreach (var rig in rigs)
|
||||
{
|
||||
rig.weight = weight;
|
||||
}
|
||||
}
|
||||
|
||||
// private void Update()
|
||||
// {
|
||||
// StartCoroutine(UpdateWeight());
|
||||
// }
|
||||
|
||||
// private IEnumerator UpdateWeight()
|
||||
// {
|
||||
// if(distanceRange == 0 || rigs == null)
|
||||
// {
|
||||
// yield break;
|
||||
// }
|
||||
// yield return new WaitForEndOfFrame();
|
||||
// float distance = Vector3.Distance(source.position, target.position);
|
||||
// float weight = Mathf.Lerp(0, 1, (distanceMax - distance) / distanceRange);
|
||||
// foreach (Rig rig in rigs)
|
||||
// {
|
||||
// rig.weight = Mathf.Lerp(rig.weight, weight, 0.5f);
|
||||
// if(weight > 0 && weight < 1)
|
||||
// Log.Out("ratio: " + ((distanceMax - distance) / distanceRange).ToString() + " weight: " + weight.ToString());
|
||||
// }
|
||||
|
||||
//#if UNITY_EDITOR
|
||||
// if (logDistance)
|
||||
// {
|
||||
// Log.Out(Vector3.Distance(source.position, target.position).ToString());
|
||||
// }
|
||||
//#endif
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b22553f7e0b6104dac02ca4c8af2c99
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
KFAttached/Animation/StateMachineBehaviours.meta
Normal file
8
KFAttached/Animation/StateMachineBehaviours.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 664ef95b745768746a23509d7b250fdd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimationAimRecoilResetState : StateMachineBehaviour
|
||||
{
|
||||
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
animator.GetComponent<AnimationAimRecoilReferences>()?.Rollback();
|
||||
}
|
||||
|
||||
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
animator.GetComponent<AnimationAimRecoilReferences>()?.Rollback();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 248236ebc388e4c4d8e3f700b7444ab6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
#if NotEditor
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
using KFCommonUtilityLib.Scripts.Utilities;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimationAmmoUpdateState : StateMachineBehaviour
|
||||
{
|
||||
#if NotEditor
|
||||
private static int[] hash_states = new[]
|
||||
{
|
||||
Animator.StringToHash("ammoCount"),
|
||||
Animator.StringToHash("ammoCount1"),
|
||||
Animator.StringToHash("ammoCount2"),
|
||||
Animator.StringToHash("ammoCount3"),
|
||||
Animator.StringToHash("ammoCount4")
|
||||
};
|
||||
private InventorySlotGurad slotGuard = new InventorySlotGurad();
|
||||
|
||||
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
//var player = GameManager.Instance.World?.GetPrimaryPlayer();
|
||||
var player = animator.GetComponentInParent<EntityAlive>();
|
||||
if(slotGuard.IsValid(player))
|
||||
{
|
||||
SetAmmoCountForEntity(player, slotGuard.Slot);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetAmmoCountForEntity(EntityAlive entity, int slot)
|
||||
{
|
||||
if (entity)
|
||||
{
|
||||
var invData = entity.inventory?.slots?[slot];
|
||||
if (invData?.actionData != null)
|
||||
{
|
||||
var mapping = MultiActionManager.GetMappingForEntity(entity.entityId);
|
||||
if (mapping != null)
|
||||
{
|
||||
var metaIndices = mapping.indices;
|
||||
for (int i = 0; i < mapping.ModeCount; i++)
|
||||
{
|
||||
int metaIndex = metaIndices.GetMetaIndexForMode(i);
|
||||
int meta = invData.itemValue.GetMetaByMode(i);
|
||||
entity.emodel.avatarController.UpdateInt(hash_states[metaIndex], meta);
|
||||
if (ConsoleCmdReloadLog.LogInfo)
|
||||
{
|
||||
Log.Out($"Setting ammoCount{(metaIndex > 0 ? metaIndex.ToString() : "")} to {meta}, stack trace:\n{StackTraceUtility.ExtractStackTrace()}");
|
||||
}
|
||||
//animator.SetInteger(hash_states[metaIndex], meta);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.emodel.avatarController.UpdateInt(hash_states[0], invData.itemValue.Meta);
|
||||
if (ConsoleCmdReloadLog.LogInfo)
|
||||
{
|
||||
Log.Out($"Setting ammoCount to {invData.itemValue.Meta}, stack trace:\n{StackTraceUtility.ExtractStackTrace()}");
|
||||
}
|
||||
//animator.SetInteger(hash_states[0], entity.inventory.holdingItemItemValue.Meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87658b6a8bedcd14e83febff2157048c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,266 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.Animations;
|
||||
#endif
|
||||
|
||||
public class AnimationCustomMeleeAttackState : StateMachineBehaviour
|
||||
#if UNITY_EDITOR
|
||||
, ISerializationCallbackReceiver
|
||||
#endif
|
||||
{
|
||||
public float RaycastTime = 0.3f;
|
||||
public float CustomGrazeCastTime = 0.3f;
|
||||
public float CustomGrazeCastDuration = 0f;
|
||||
public float ImpactDuration = 0.01f;
|
||||
[Range(0.01f, 1f)]
|
||||
public float ImpactPlaybackSpeed = 1f;
|
||||
[Range(0.01f, 1f)]
|
||||
public float attackDurationNormalized = 1f;
|
||||
[Range(0f, 360f)]
|
||||
public float SwingAngle = 0f;
|
||||
[Range(-180f, 180f)]
|
||||
public float SwingDegrees = 0f;
|
||||
|
||||
[SerializeField]
|
||||
private float ClipLength = 0f;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
var context = AnimatorController.FindStateMachineBehaviourContext(this);
|
||||
if (context != null && context.Length > 0)
|
||||
{
|
||||
var state = context[0].animatorObject as AnimatorState;
|
||||
if (state != null)
|
||||
{
|
||||
var clip = state.motion as AnimationClip;
|
||||
if (clip != null)
|
||||
{
|
||||
ClipLength = clip.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NotEditor
|
||||
private readonly int AttackSpeedHash = Animator.StringToHash("MeleeAttackSpeed");
|
||||
private float calculatedRaycastTime;
|
||||
private float calculatedGrazeTime;
|
||||
private float calculatedGrazeDuration;
|
||||
private float calculatedImpactDuration;
|
||||
private float calculatedImpactPlaybackSpeed;
|
||||
private bool hasFired;
|
||||
private int actionIndex;
|
||||
private float originalMeleeAttackSpeed;
|
||||
//private bool playingImpact;
|
||||
private EntityAlive entity;
|
||||
private float attacksPerMinute;
|
||||
private float speedMultiplierToKeep = 1f;
|
||||
private InventorySlotGurad slotGurad = new InventorySlotGurad();
|
||||
|
||||
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
//if (playingImpact)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
hasFired = false;
|
||||
actionIndex = animator.GetWrappedInt(AvatarController.itemActionIndexHash);
|
||||
entity = animator.GetComponentInParent<EntityAlive>();
|
||||
if (!slotGurad.IsValid(entity))
|
||||
{
|
||||
return;
|
||||
}
|
||||
//Log.Out("State entered!");
|
||||
//AnimatorClipInfo[] array = animator.GetNextAnimatorClipInfo(layerIndex);
|
||||
float length = ClipLength * attackDurationNormalized;
|
||||
////if (array.Length == 0)
|
||||
////{
|
||||
// var array = animator.GetCurrentAnimatorClipInfo(layerIndex);
|
||||
// if (array.Length == 0)
|
||||
// {
|
||||
// if (float.IsInfinity(stateInfo.length))
|
||||
// {
|
||||
// Log.Out($"Invalid clips!");
|
||||
// return;
|
||||
// }
|
||||
// length = stateInfo.length;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// length = array[0].clip.length;
|
||||
// }
|
||||
////}
|
||||
////else
|
||||
////{
|
||||
//// length = array[0].clip.length;
|
||||
////}
|
||||
//length *= attackDurationNormalized;
|
||||
attacksPerMinute = 60f / length;
|
||||
FastTags<TagGroup.Global> fastTags = ((actionIndex != 1) ? ItemActionAttack.PrimaryTag : ItemActionAttack.SecondaryTag);
|
||||
ItemValue holdingItemItemValue = entity.inventory.holdingItemItemValue;
|
||||
ItemClass itemClass = holdingItemItemValue.ItemClass;
|
||||
if (itemClass != null)
|
||||
{
|
||||
fastTags |= itemClass.ItemTags;
|
||||
}
|
||||
originalMeleeAttackSpeed = EffectManager.GetValue(PassiveEffects.AttacksPerMinute, holdingItemItemValue, attacksPerMinute, entity, null, fastTags) / 60f * length;
|
||||
animator.SetWrappedFloat(AttackSpeedHash, originalMeleeAttackSpeed);
|
||||
speedMultiplierToKeep = originalMeleeAttackSpeed;
|
||||
ItemClass holdingItem = entity.inventory.holdingItem;
|
||||
holdingItem.Properties.ParseFloat((actionIndex != 1) ? "Action0.RaycastTime" : "Action1.RaycastTime", ref RaycastTime);
|
||||
float impactDuration = -1f;
|
||||
holdingItem.Properties.ParseFloat((actionIndex != 1) ? "Action0.ImpactDuration" : "Action1.ImpactDuration", ref impactDuration);
|
||||
if (impactDuration >= 0f)
|
||||
{
|
||||
ImpactDuration = impactDuration * originalMeleeAttackSpeed;
|
||||
}
|
||||
holdingItem.Properties.ParseFloat((actionIndex != 1) ? "Action0.ImpactPlaybackSpeed" : "Action1.ImpactPlaybackSpeed", ref ImpactPlaybackSpeed);
|
||||
if (originalMeleeAttackSpeed != 0f)
|
||||
{
|
||||
calculatedRaycastTime = RaycastTime / originalMeleeAttackSpeed;
|
||||
calculatedGrazeTime = CustomGrazeCastTime / originalMeleeAttackSpeed;
|
||||
calculatedGrazeDuration = CustomGrazeCastDuration / originalMeleeAttackSpeed;
|
||||
calculatedImpactDuration = ImpactDuration / originalMeleeAttackSpeed;
|
||||
calculatedImpactPlaybackSpeed = ImpactPlaybackSpeed * originalMeleeAttackSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
calculatedRaycastTime = 0.001f;
|
||||
calculatedGrazeTime = 0.001f;
|
||||
calculatedGrazeDuration = 0.001f;
|
||||
calculatedImpactDuration = 0.001f;
|
||||
calculatedImpactPlaybackSpeed = 0.001f;
|
||||
}
|
||||
if (ConsoleCmdReloadLog.LogInfo)
|
||||
{
|
||||
Log.Out($"original: raycast time {RaycastTime} impact duration {ImpactDuration} impact playback speed {ImpactPlaybackSpeed} clip length {length}/{stateInfo.length}");
|
||||
Log.Out($"calculated: raycast time {calculatedRaycastTime} impact duration {calculatedImpactDuration} impact playback speed {calculatedImpactPlaybackSpeed} speed multiplier {originalMeleeAttackSpeed}");
|
||||
}
|
||||
GameManager.Instance.StartCoroutine(impactStart(animator, layerIndex, length));
|
||||
GameManager.Instance.StartCoroutine(customGrazeStart(length));
|
||||
}
|
||||
|
||||
private IEnumerator impactStart(Animator animator, int layer, float length)
|
||||
{
|
||||
yield return new WaitForSeconds(Mathf.Max(calculatedRaycastTime, 0));
|
||||
if (!hasFired)
|
||||
{
|
||||
hasFired = true;
|
||||
if (entity != null && !entity.isEntityRemote && actionIndex >= 0)
|
||||
{
|
||||
ItemActionDynamicMelee.ItemActionDynamicMeleeData itemActionDynamicMeleeData = entity.inventory.holdingItemData.actionData[actionIndex] as ItemActionDynamicMelee.ItemActionDynamicMeleeData;
|
||||
if (itemActionDynamicMeleeData != null)
|
||||
{
|
||||
if ((entity.inventory.holdingItem.Actions[actionIndex] as ItemActionDynamicMelee).Raycast(itemActionDynamicMeleeData))
|
||||
{
|
||||
GameManager.Instance.StartCoroutine(impactStop(animator, layer, length));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
private IEnumerator impactStop(Animator animator, int layer, float length)
|
||||
{
|
||||
//playingImpact = true;
|
||||
//animator.Play(0, layer, Mathf.Min(1f, calculatedRaycastTime * attackDurationNormalized / length));
|
||||
if (animator)
|
||||
{
|
||||
//Log.Out("Impact start!");
|
||||
animator.SetWrappedFloat(AttackSpeedHash, calculatedImpactPlaybackSpeed);
|
||||
}
|
||||
speedMultiplierToKeep = calculatedImpactPlaybackSpeed;
|
||||
yield return new WaitForSeconds(calculatedImpactDuration);
|
||||
if (animator)
|
||||
{
|
||||
//Log.Out("Impact stop!");
|
||||
animator.SetWrappedFloat(AttackSpeedHash, originalMeleeAttackSpeed);
|
||||
}
|
||||
speedMultiplierToKeep = originalMeleeAttackSpeed;
|
||||
//playingImpact = false;
|
||||
yield break;
|
||||
}
|
||||
|
||||
private IEnumerator customGrazeStart(float length)
|
||||
{
|
||||
if (ConsoleCmdReloadLog.LogInfo)
|
||||
{
|
||||
Log.Out($"Custom graze time: {calculatedGrazeTime} original {CustomGrazeCastTime}");
|
||||
}
|
||||
yield return new WaitForSeconds(calculatedGrazeTime);
|
||||
if (entity != null && !entity.isEntityRemote && actionIndex >= 0)
|
||||
{
|
||||
ItemActionDynamicMelee.ItemActionDynamicMeleeData itemActionDynamicMeleeData = entity.inventory.holdingItemData.actionData[actionIndex] as ItemActionDynamicMelee.ItemActionDynamicMeleeData;
|
||||
if (itemActionDynamicMeleeData != null)
|
||||
{
|
||||
GameManager.Instance.StartCoroutine(customGrazeUpdate(itemActionDynamicMeleeData));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator customGrazeUpdate(ItemActionDynamicMelee.ItemActionDynamicMeleeData data)
|
||||
{
|
||||
if (ConsoleCmdReloadLog.LogInfo)
|
||||
{
|
||||
Log.Out($"Custom graze duration: {calculatedGrazeDuration} original {CustomGrazeCastDuration}");
|
||||
}
|
||||
if (calculatedGrazeDuration <= 0f)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
float grazeStart = Time.time;
|
||||
float normalizedTime = 0f;
|
||||
var action = entity.inventory.holdingItem.Actions[actionIndex] as ItemActionDynamicMelee;
|
||||
while (normalizedTime <= 1)
|
||||
{
|
||||
if (!slotGurad.IsValid(data.invData.holdingEntity))
|
||||
{
|
||||
Log.Out($"Invalid graze!");
|
||||
yield break;
|
||||
}
|
||||
float originalSwingAngle = action.SwingAngle;
|
||||
float originalSwingDegrees = action.SwingDegrees;
|
||||
action.SwingAngle = SwingAngle;
|
||||
action.SwingDegrees = SwingDegrees;
|
||||
bool grazeResult = action.GrazeCast(data, normalizedTime);
|
||||
if (ConsoleCmdReloadLog.LogInfo)
|
||||
{
|
||||
Log.Out($"GrazeCast {grazeResult}!");
|
||||
}
|
||||
action.SwingAngle = originalSwingAngle;
|
||||
action.SwingDegrees = originalSwingDegrees;
|
||||
yield return null;
|
||||
normalizedTime = (Time.time - grazeStart) / calculatedGrazeDuration;
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
//if (entity != null && !entity.isEntityRemote && actionIndex >= 0 && entity.inventory.holdingItemData.actionData[actionIndex] is ItemActionDynamicMelee.ItemActionDynamicMeleeData)
|
||||
//{
|
||||
// animator.SetFloat(AttackSpeedHash, originalMeleeAttackSpeed);
|
||||
//}
|
||||
animator.SetWrappedFloat(AttackSpeedHash, originalMeleeAttackSpeed);
|
||||
}
|
||||
|
||||
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
//float normalizedTime = stateInfo.normalizedTime;
|
||||
//if (float.IsInfinity(normalizedTime) || float.IsNaN(normalizedTime))
|
||||
//{
|
||||
// animator.Play(animator.GetNextAnimatorStateInfo(layerIndex).shortNameHash, layerIndex);
|
||||
//}
|
||||
animator.SetWrappedFloat(AttackSpeedHash, speedMultiplierToKeep);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fef84a89943f52c418487a560eb789c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,94 @@
|
||||
#if NotEditor
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimationCustomReloadState : StateMachineBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private float ForceCancelReloadDelay = 1f;
|
||||
[SerializeField]
|
||||
private bool DoNotForceCancel = false;
|
||||
|
||||
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
animator.speed = 1f;
|
||||
animator.SetWrappedBool(Animator.StringToHash("Reload"), false);
|
||||
animator.SetWrappedBool(Animator.StringToHash("IsReloading"), true);
|
||||
#if NotEditor
|
||||
if (player == null)
|
||||
{
|
||||
player = animator.GetComponentInParent<EntityAlive>();
|
||||
}
|
||||
int actionIndex = MultiActionManager.GetActionIndexForEntity(player);
|
||||
#if DEBUG
|
||||
Log.Out($"start reload {actionIndex}");
|
||||
#endif
|
||||
actionData = player.inventory.holdingItemData.actionData[actionIndex] as ItemActionRanged.ItemActionDataRanged;
|
||||
if (eventBridge == null)
|
||||
{
|
||||
eventBridge = animator.GetComponent<AnimationReloadEvents>();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
Log.Out($"ANIMATOR STATE ENTER : {actionData.invData.item.Name}");
|
||||
#endif
|
||||
eventBridge.OnReloadStart(actionIndex);
|
||||
//eventBridge.OnReloadUpdate();
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
animator.speed = 1f;
|
||||
#if NotEditor
|
||||
//eventBridge.OnReloadUpdate();
|
||||
if (actionData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (actionData.isReloading)
|
||||
{
|
||||
eventBridge.OnReloadFinish();
|
||||
}
|
||||
#endif
|
||||
//actionData.isReloading = false;
|
||||
//actionData.isReloadCancelled = false;
|
||||
//actionData.isChangingAmmoType = false;
|
||||
#if DEBUG && NotEditor
|
||||
Log.Out($"ANIMATOR STATE EXIT : {actionData.invData.item.Name}");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NotEditor
|
||||
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
//eventBridge.OnReloadUpdate();
|
||||
if (actionData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (actionData.isReloadCancelled)
|
||||
{
|
||||
animator.speed = 30f;
|
||||
|
||||
if (!DoNotForceCancel)
|
||||
{
|
||||
eventBridge.DelayForceCancelReload(ForceCancelReloadDelay);
|
||||
}
|
||||
#if DEBUG
|
||||
Log.Out($"ANIMATOR UPDATE: RELOAD CANCELLED, ANIMATOR SPEED {animator.speed}");
|
||||
#endif
|
||||
}
|
||||
if (!actionData.isReloadCancelled && actionData.isReloading)
|
||||
{
|
||||
actionData.invData.holdingEntity.MinEventContext.ItemActionData = actionData;
|
||||
actionData.invData.holdingEntity.FireEvent(MinEventTypes.onReloadUpdate, true);
|
||||
}
|
||||
}
|
||||
|
||||
private ItemActionRanged.ItemActionDataRanged actionData;
|
||||
private EntityAlive player;
|
||||
private AnimationReloadEvents eventBridge;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f156c87129f85044a3336ade4d1af2c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations.Rigging;
|
||||
|
||||
public class AnimationInspectFix : MonoBehaviour, IPlayableGraphRelated
|
||||
{
|
||||
[SerializeField]
|
||||
private string inspectName = "Inspect";
|
||||
[SerializeField]
|
||||
private int layer = 0;
|
||||
[SerializeField, Range(0, 1)]
|
||||
private float finishTime = 1;
|
||||
[SerializeField]
|
||||
private bool useStateTag = false;
|
||||
private static int inspectHash = Animator.StringToHash("weaponInspect");
|
||||
private IAnimatorWrapper wrapper;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (wrapper == null || !wrapper.IsValid)
|
||||
{
|
||||
var animator = GetComponent<Animator>();
|
||||
if (!animator)
|
||||
{
|
||||
Destroy(this);
|
||||
return;
|
||||
}
|
||||
wrapper = animator.GetItemAnimatorWrapper();
|
||||
}
|
||||
if (useStateTag)
|
||||
{
|
||||
var stateInfo = wrapper.GetCurrentAnimatorStateInfo(layer);
|
||||
if (stateInfo.IsTag(inspectName) && stateInfo.normalizedTime < finishTime)
|
||||
{
|
||||
wrapper.ResetTrigger(inspectHash);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var transInfo = wrapper.GetAnimatorTransitionInfo(layer);
|
||||
if (transInfo.IsUserName(inspectName) && transInfo.normalizedTime < finishTime)
|
||||
{
|
||||
wrapper.ResetTrigger(inspectHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MonoBehaviour Init(Transform playerAnimatorTrans, bool isLocalPlayer)
|
||||
{
|
||||
enabled = false;
|
||||
var copy = isLocalPlayer ? playerAnimatorTrans.AddMissingComponent<AnimationInspectFix>() : null;
|
||||
if (copy)
|
||||
{
|
||||
copy.enabled = true;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
public void Disable(Transform playerAnimatorTrans)
|
||||
{
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26c7436085cc1924a882f62d81f262a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,41 @@
|
||||
#if NotEditor
|
||||
using KFCommonUtilityLib;
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimationLockAction : StateMachineBehaviour
|
||||
{
|
||||
public bool lockReload = false;
|
||||
#if NotEditor
|
||||
private InventorySlotGurad slotGuard = new InventorySlotGurad();
|
||||
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
var player = animator.GetComponentInParent<EntityAlive>();
|
||||
if (slotGuard.IsValid(player))
|
||||
{
|
||||
if (player.inventory.holdingItemData.actionData[MultiActionManager.GetActionIndexForEntity(player)] is IModuleContainerFor<ActionModuleAnimationLocked.AnimationLockedData> lockData)
|
||||
{
|
||||
lockData.Instance.isLocked = true;
|
||||
if (lockReload)
|
||||
{
|
||||
lockData.Instance.isReloadLocked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
var player = animator.GetComponentInParent<EntityAlive>();
|
||||
if (slotGuard.IsValid(player))
|
||||
{
|
||||
if (player.inventory.holdingItemData.actionData[MultiActionManager.GetActionIndexForEntity(player)] is IModuleContainerFor<ActionModuleAnimationLocked.AnimationLockedData> lockData)
|
||||
{
|
||||
lockData.Instance.isLocked = false;
|
||||
lockData.Instance.isReloadLocked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41af3d052f5a46a4c86c3ffbaf4c7918
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,85 @@
|
||||
#if NotEditor
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
using UAI;
|
||||
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimationMultiStageReloadState : StateMachineBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private bool speedUpOnCancel;
|
||||
[SerializeField]
|
||||
private bool immediateCancel;
|
||||
[SerializeField]
|
||||
private float ForceCancelReloadDelay = 1f;
|
||||
[SerializeField]
|
||||
private bool DoNotForceCancel = false;
|
||||
|
||||
private AnimationReloadEvents eventBridge;
|
||||
|
||||
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
animator.SetWrappedBool(Animator.StringToHash("Reload"), false);
|
||||
if (eventBridge == null)
|
||||
{
|
||||
eventBridge = animator.GetComponent<AnimationReloadEvents>();
|
||||
}
|
||||
if (stateInfo.IsTag("ReloadStart"))
|
||||
{
|
||||
animator.speed = 1f;
|
||||
animator.SetWrappedBool(Animator.StringToHash("IsReloading"), true);
|
||||
#if NotEditor
|
||||
EntityAlive player = animator.GetComponentInParent<EntityAlive>();
|
||||
int actionIndex = MultiActionManager.GetActionIndexForEntity(player);
|
||||
eventBridge.OnReloadStart(actionIndex);
|
||||
#if DEBUG
|
||||
Log.Out($"start reload {actionIndex}");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if NotEditor
|
||||
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
var actionData = eventBridge.actionData;
|
||||
if (actionData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionData.isReloadCancelled)
|
||||
{
|
||||
if (speedUpOnCancel)
|
||||
{
|
||||
Log.Out("Speed up animation!");
|
||||
animator.speed = 30;
|
||||
}
|
||||
|
||||
if (immediateCancel)
|
||||
{
|
||||
animator.SetBool("IsReloading", false);
|
||||
}
|
||||
|
||||
if (!DoNotForceCancel)
|
||||
{
|
||||
eventBridge.DelayForceCancelReload(ForceCancelReloadDelay);
|
||||
}
|
||||
}
|
||||
|
||||
if (actionData.isReloading && animator.GetBool("IsReloading"))
|
||||
{
|
||||
actionData.invData.holdingEntity.MinEventContext.ItemActionData = actionData;
|
||||
actionData.invData.holdingEntity.FireEvent(MinEventTypes.onReloadUpdate, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
animator.speed = 1f;
|
||||
if (stateInfo.IsTag("ReloadEnd"))
|
||||
eventBridge?.OnReloadFinish();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a36e127f3f92d4f4a8c3e3fdabe6e1d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimationRandomRecoilState : StateMachineBehaviour
|
||||
{
|
||||
[SerializeField] private Vector3 positionMultiplier = Vector3.one;
|
||||
[SerializeField] private Vector3 rotationMultiplier = Vector3.one;
|
||||
|
||||
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
animator.GetComponent<AnimationProceduralRecoildAbs>()?.AddRecoil(positionMultiplier, rotationMultiplier);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a853564a7472fea44b9ba42cbf3ae654
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimationResetRigWeightState : StateMachineBehaviour
|
||||
{
|
||||
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
animator.GetComponent<RigWeightOverTime>()?.SetWeight(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cfcbf05cdb32514bab41d81a761cd4d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations;
|
||||
using UnityEngine.Animations.Rigging;
|
||||
|
||||
public class AnimationRigLayerController : StateMachineBehaviour, ISerializationCallbackReceiver
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[Serializable]
|
||||
public struct State
|
||||
{
|
||||
public byte layer;
|
||||
public bool enable;
|
||||
}
|
||||
[SerializeField]
|
||||
public State[] layerStatesEditor;
|
||||
#endif
|
||||
[SerializeField, HideInInspector]
|
||||
private int[] layers;
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if(layerStatesEditor != null)
|
||||
{
|
||||
layers = new int[layerStatesEditor.Length];
|
||||
for (int i = 0; i < layerStatesEditor.Length; i++)
|
||||
{
|
||||
layers[i] = layerStatesEditor[i].layer | (layerStatesEditor[i].enable ? 0 : 0x8000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
if (layers == null)
|
||||
return;
|
||||
|
||||
RigBuilder rigBuilder = animator.GetComponent<RigBuilder>();
|
||||
if (rigBuilder && rigBuilder.layers != null)
|
||||
{
|
||||
foreach (var layer in layers)
|
||||
{
|
||||
int realLayer = layer & 0x7fff;
|
||||
if (realLayer >= rigBuilder.layers.Count)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
rigBuilder.layers[realLayer].active = (layer & 0x8000) <= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dbb26fa6f1fef8f45b8eaf5702207898
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,45 @@
|
||||
using UnityEngine;
|
||||
|
||||
[AddComponentMenu("KFAttachments/Utils/Animator Random Switch")]
|
||||
public class AnimatorRandomSwitch : StateMachineBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private string parameter;
|
||||
[SerializeField]
|
||||
private int stateCount;
|
||||
|
||||
private int[] stateHits;
|
||||
int totalHits;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
stateHits = new int[stateCount];
|
||||
for (int i = 0; i < stateCount; i++)
|
||||
{
|
||||
stateHits[i] = 1;
|
||||
}
|
||||
totalHits = stateCount;
|
||||
}
|
||||
|
||||
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
int rand = Random.Range(0, totalHits);
|
||||
int cur = 0;
|
||||
bool found = false;
|
||||
for (int i = 0; i < stateHits.Length; i++)
|
||||
{
|
||||
cur += stateHits[i];
|
||||
if (cur > rand && !found)
|
||||
{
|
||||
animator.SetInteger(parameter, i);
|
||||
found = true;
|
||||
stateHits[i] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stateHits[i] = 2;
|
||||
}
|
||||
}
|
||||
totalHits = stateCount * 2 - 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c083a728c43231842a2e50a3c04b4a11
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user