From f975b84aaea32e41daaba5050a5407221f30d50c Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Tue, 9 Mar 2021 13:44:47 -0500 Subject: [PATCH 01/14] fixing mage base attack. fixing chasing on attack action. making imps aggro on damage. --- .../Action/Archer/ArcherChargedShot.asset | 4 +-- .../GameData/Action/General/Chase.asset | 4 +-- .../GameData/Action/General/Emote1.asset | 4 +-- .../GameData/Action/General/Emote2.asset | 4 +-- .../GameData/Action/General/Emote3.asset | 4 +-- .../GameData/Action/General/Emote4.asset | 4 +-- .../GameData/Action/General/Revive.asset | 4 +-- .../GameData/Action/Mage/MageBaseAttack.asset | 4 +-- .../Action/Rogue/RogueStealthMode.asset | 4 +-- .../Action/FXProjectileTargetedActionFX.cs | 12 +++---- .../Client/Game/Action/TargetActionFX.cs | 17 +++++++--- .../Game/Character/ClientGenericMovement.cs | 2 -- .../Game/Character/ClientInputSender.cs | 31 ++++++++--------- .../Scripts/Server/Game/Action/Action.cs | 6 ++-- .../Server/Game/Action/ActionPlayer.cs | 34 ++++++++++++++++--- .../Game/Action/FXProjectileTargetedAction.cs | 4 +-- .../Scripts/Server/Game/Character/AIBrain.cs | 13 +++++++ .../Server/Game/Character/ServerCharacter.cs | 6 ++++ .../Scripts/Shared/Data/ActionDescription.cs | 4 +++ .../Shared/Game/Action/ActionRequestData.cs | 1 + .../Scripts/Shared/Game/Action/ActionUtils.cs | 9 ++--- .../Scripts/Shared/Game/Entity/ITargetable.cs | 20 +++++++++++ .../Shared/Game/Entity/ITargetable.cs.meta | 11 ++++++ .../Game/Entity/NetworkBreakableState.cs | 6 +++- .../Game/Entity/NetworkCharacterState.cs | 4 ++- 25 files changed, 153 insertions(+), 63 deletions(-) create mode 100644 Assets/BossRoom/Scripts/Shared/Game/Entity/ITargetable.cs create mode 100644 Assets/BossRoom/Scripts/Shared/Game/Entity/ITargetable.cs.meta diff --git a/Assets/BossRoom/GameData/Action/Archer/ArcherChargedShot.asset b/Assets/BossRoom/GameData/Action/Archer/ArcherChargedShot.asset index 81e74009c..c015af111 100644 --- a/Assets/BossRoom/GameData/Action/Archer/ArcherChargedShot.asset +++ b/Assets/BossRoom/GameData/Action/Archer/ArcherChargedShot.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e033f2968c36246c470a8964a58064e316f9d5d737e71bc543de9ccf1a3c5566 -size 1668 +oid sha256:cc2a1897d7481e9175e942ff9fddc495d84b0daace2ab96f21cfbad2a6d7dfa3 +size 1693 diff --git a/Assets/BossRoom/GameData/Action/General/Chase.asset b/Assets/BossRoom/GameData/Action/General/Chase.asset index c902c3b6c..6723ed755 100644 --- a/Assets/BossRoom/GameData/Action/General/Chase.asset +++ b/Assets/BossRoom/GameData/Action/General/Chase.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f95c9f9484b5499018e27f100ab8db26907bfb04456f847f5f2af1d3f97a0d01 -size 819 +oid sha256:d5b5705fc6877e0ba83bd48f12254c34cabcfb11135f2300e4c65f59a10cf1c5 +size 844 diff --git a/Assets/BossRoom/GameData/Action/General/Emote1.asset b/Assets/BossRoom/GameData/Action/General/Emote1.asset index ff59b8727..21ce80dd0 100644 --- a/Assets/BossRoom/GameData/Action/General/Emote1.asset +++ b/Assets/BossRoom/GameData/Action/General/Emote1.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8be703ef7e2ba53d4cb5102728e021dd44bfa50309971725ce878b5e17d0e153 -size 827 +oid sha256:7d7a3562dcef98fdd8a3cc3e05260fc20347c657447f8c73e2f4a7c210660d3b +size 852 diff --git a/Assets/BossRoom/GameData/Action/General/Emote2.asset b/Assets/BossRoom/GameData/Action/General/Emote2.asset index f2213e6e4..8ad821b88 100644 --- a/Assets/BossRoom/GameData/Action/General/Emote2.asset +++ b/Assets/BossRoom/GameData/Action/General/Emote2.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8843abe3dc034d608e43404c2127eabec65980831856feb9c55f245646e4d374 -size 831 +oid sha256:a5a94ce5639e8dfd8779f6bd62ad091829be81d32a3a1010e1a56f319ec2859d +size 856 diff --git a/Assets/BossRoom/GameData/Action/General/Emote3.asset b/Assets/BossRoom/GameData/Action/General/Emote3.asset index 8901d293b..17b6edb8d 100644 --- a/Assets/BossRoom/GameData/Action/General/Emote3.asset +++ b/Assets/BossRoom/GameData/Action/General/Emote3.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d6c62a92b1e65b1ce7c14f2a92b82408de642506569a879b429e2f7f87dc62d -size 831 +oid sha256:a3383a6d804ec69bfc02cece3b9185af3013c771933258ee5c52f63503292596 +size 856 diff --git a/Assets/BossRoom/GameData/Action/General/Emote4.asset b/Assets/BossRoom/GameData/Action/General/Emote4.asset index b834c10e3..b1be61e5c 100644 --- a/Assets/BossRoom/GameData/Action/General/Emote4.asset +++ b/Assets/BossRoom/GameData/Action/General/Emote4.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0f22b92ccb27eecf0a53e29c83e8bfb138fbc93f914ea10454e064c1e5b84b3 -size 827 +oid sha256:d0e7d6adee1d76e533c911294eb46fc725703b29da36bcbb421b757a22571951 +size 852 diff --git a/Assets/BossRoom/GameData/Action/General/Revive.asset b/Assets/BossRoom/GameData/Action/General/Revive.asset index dd319bead..a3f5c622e 100644 --- a/Assets/BossRoom/GameData/Action/General/Revive.asset +++ b/Assets/BossRoom/GameData/Action/General/Revive.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3012e879ec23799e43ad48d3c9b1df8f984a5f864d378c0b3d1752aa971db3f1 -size 744 +oid sha256:bbc1c14f35b828ccdfc656f1bb6e00c92d659dd859aff843a5e1f6f51083e803 +size 847 diff --git a/Assets/BossRoom/GameData/Action/Mage/MageBaseAttack.asset b/Assets/BossRoom/GameData/Action/Mage/MageBaseAttack.asset index 821d24230..524eb44e4 100644 --- a/Assets/BossRoom/GameData/Action/Mage/MageBaseAttack.asset +++ b/Assets/BossRoom/GameData/Action/Mage/MageBaseAttack.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4fc968ccb9231edee95d1aa87b2fd2fc58a12c81ea85deca470da3b1a3c7f358 -size 1064 +oid sha256:8edafce485a5b0b0dc6e9dea20045a22adc3b0cb653df8dfe6ba2d59cd7eceee +size 1094 diff --git a/Assets/BossRoom/GameData/Action/Rogue/RogueStealthMode.asset b/Assets/BossRoom/GameData/Action/Rogue/RogueStealthMode.asset index a9f8f68aa..b33019a34 100644 --- a/Assets/BossRoom/GameData/Action/Rogue/RogueStealthMode.asset +++ b/Assets/BossRoom/GameData/Action/Rogue/RogueStealthMode.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a62ef56dabdf8a160e749dec0b5821d32af0c958703803c0f1922fd8eb075b3f -size 1114 +oid sha256:cfbc9679d36eaa6faafb7eeb1ddee2261f56a33090ce9bec7d0579ab8e3ef989 +size 1139 diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs index 2c3885049..3e9b41e9f 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs @@ -21,7 +21,7 @@ public FXProjectileTargetedActionFX(ref ActionRequestData data, ClientCharacterV private FXProjectile m_Projectile; // the enemy we're aiming at - private Client.ClientCharacter m_Target; + private NetworkObject m_Target; public override bool Start() { @@ -79,10 +79,10 @@ private void PlayHitReact() return; m_ImpactPlayed = true; - if (m_Target) + if (m_Target && m_Target.TryGetComponent(out Client.ClientCharacter clientCharacter) && clientCharacter.ChildVizObject != null ) { - ClientCharacterVisualization targetViz = m_Target.GetComponent().ChildVizObject; - targetViz.OurAnimator.SetTrigger("HitReact1"); + var hitReact = !string.IsNullOrEmpty(Description.ReactAnim) ? Description.ReactAnim : "HitReact1"; + clientCharacter.ChildVizObject.OurAnimator.SetTrigger(hitReact); } } @@ -94,7 +94,7 @@ private bool HasTarget() return Data.TargetIds != null && Data.TargetIds.Length > 0; } - private Client.ClientCharacter GetTarget() + private NetworkObject GetTarget() { if (Data.TargetIds == null || Data.TargetIds.Length == 0) { @@ -104,7 +104,7 @@ private Client.ClientCharacter GetTarget() NetworkObject obj; if (NetworkSpawnManager.SpawnedObjects.TryGetValue(Data.TargetIds[0], out obj) && obj != null) { - return obj.GetComponent(); + return obj; } else { diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs index b7a0086ad..8e44e0d5f 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs @@ -32,14 +32,23 @@ public override bool Update() if( m_CurrentTarget != m_ParentState.TargetId.Value ) { m_CurrentTarget = m_ParentState.TargetId.Value; + if (NetworkSpawnManager.SpawnedObjects.TryGetValue(m_CurrentTarget, out NetworkObject targetObject ) ) { - var targetChar = targetObject.GetComponent(); - if( targetChar != null ) + var targetEntity = targetObject?.GetComponent(); + if( targetEntity != null ) { ValidateReticule(targetObject); m_TargetReticule.SetActive(true); - m_TargetReticule.transform.parent = targetChar.ChildVizObject.transform; //attach to the GRAPHICS GameObject of the target. + + var parentTransform = targetObject.transform; + if( targetObject.TryGetComponent(out Client.ClientCharacter clientCharacter)) + { + //for characters, attach the reticule to the child graphics object. + parentTransform = clientCharacter.ChildVizObject.transform; + } + + m_TargetReticule.transform.parent = parentTransform; m_TargetReticule.transform.localPosition = new Vector3(0, k_ReticuleGroundHeight, 0); } @@ -65,7 +74,7 @@ private void ValidateReticule(NetworkObject targetObject) m_TargetReticule = Object.Instantiate(m_Parent.TargetReticule); } - bool target_isnpc = targetObject.GetComponent().CharacterData.IsNpc; + bool target_isnpc = targetObject.GetComponent().IsNpc; bool myself_isnpc = m_ParentState.CharacterData.IsNpc; bool hostile = target_isnpc != myself_isnpc; diff --git a/Assets/BossRoom/Scripts/Client/Game/Character/ClientGenericMovement.cs b/Assets/BossRoom/Scripts/Client/Game/Character/ClientGenericMovement.cs index 57add9ae7..eb51eaa3a 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Character/ClientGenericMovement.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Character/ClientGenericMovement.cs @@ -18,8 +18,6 @@ public class ClientGenericMovement : MLAPI.NetworkBehaviour void Start() { m_MovementSource = GetComponent(); - m_MovementSource.InitNetworkPositionAndRotationY(transform.position, transform.rotation.eulerAngles.y); - m_Rigidbody = GetComponent(); //this may be null. } diff --git a/Assets/BossRoom/Scripts/Client/Game/Character/ClientInputSender.cs b/Assets/BossRoom/Scripts/Client/Game/Character/ClientInputSender.cs index f4317d22b..d2c1b3c92 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Character/ClientInputSender.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Character/ClientInputSender.cs @@ -196,7 +196,7 @@ private void PerformSkill(ActionType actionType, SkillTriggerStyle triggerStyle) m_LastSentMove = Time.time; m_NetworkCharacter.RecvDoActionServerRPC(playerAction); } - else + else if(actionType != ActionType.GeneralTarget ) { // clicked on nothing... perform a "miss" attack on the spot they clicked on var data = new ActionRequestData(); @@ -224,34 +224,33 @@ private bool GetActionRequestForTarget(Transform hit, ActionType actionType, Ski if (!targetNetObj && actionType != ActionType.GeneralTarget) { ulong targetId = m_NetworkCharacter.TargetId.Value; - if (ActionUtils.IsValidTarget(targetId)) - { - targetNetObj = NetworkSpawnManager.SpawnedObjects[targetId]; - } + NetworkSpawnManager.SpawnedObjects.TryGetValue(targetId, out targetNetObj); } - var targetNetState = targetNetObj != null ? targetNetObj.GetComponent() : null; - if (targetNetState == null) + //sanity check that this is indeed a valid target. + if(targetNetObj==null || !ActionUtils.IsValidTarget(targetNetObj.NetworkObjectId)) { - //Not a Character. In the future this could represent interacting with some other interactable, but for - //now, it implies we just do nothing. return false; } - //Skill1 may be contextually overridden if it was generated from a mouse-click. - if (actionType == CharacterData.Skill1 && triggerStyle == SkillTriggerStyle.MouseClick) + var targetNetState = targetNetObj.GetComponent(); + if (targetNetState != null) { - if (!targetNetState.IsNpc && targetNetState.NetworkLifeState.Value == LifeState.Fainted) + //Skill1 may be contextually overridden if it was generated from a mouse-click. + if (actionType == CharacterData.Skill1 && triggerStyle == SkillTriggerStyle.MouseClick) { - //right-clicked on a downed ally--change the skill play to Revive. - actionType = ActionType.GeneralRevive; + if (!targetNetState.IsNpc && targetNetState.NetworkLifeState.Value == LifeState.Fainted) + { + //right-clicked on a downed ally--change the skill play to Revive. + actionType = ActionType.GeneralRevive; + } } } // record our target in case this action uses that info (non-targeted attacks will ignore this) resultData.ActionTypeEnum = actionType; - resultData.TargetIds = new ulong[] { targetNetState.NetworkObjectId }; - PopulateSkillRequest(targetNetState.transform.position, actionType, ref resultData); + resultData.TargetIds = new ulong[] { targetNetObj.NetworkObjectId }; + PopulateSkillRequest(targetNetObj.transform.position, actionType, ref resultData); return true; } diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/Action.cs b/Assets/BossRoom/Scripts/Server/Game/Action/Action.cs index 385f85482..5b12ae7ca 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/Action.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/Action.cs @@ -1,4 +1,5 @@ using UnityEngine; +using BlockingMode = BossRoom.ActionDescription.BlockingModeType; namespace BossRoom.Server { @@ -54,8 +55,9 @@ public Action(ServerCharacter parent, ref ActionRequestData data) : base(ref dat /// true to become a non-blocking Action, false to remain a blocking Action public virtual bool ShouldBecomeNonBlocking() { - return Description.BlockingMode == ActionDescription.BlockingModeType.OnlyDuringExecTime && - Time.time - TimeStarted >= Description.ExecTimeSeconds; + return Description.BlockingMode == BlockingMode.OnlyDuringExecTime ? TimeRunning >= Description.ExecTimeSeconds : + Description.BlockingMode == BlockingMode.ExecTimeWithCooldown ? TimeRunning >= (Description.ExecTimeSeconds + Description.CooldownSeconds) : + false; } /// diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs b/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs index edd52c4f4..e988b194a 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using UnityEngine; +using BlockingMode = BossRoom.ActionDescription.BlockingModeType; namespace BossRoom.Server { @@ -21,6 +22,8 @@ public class ActionPlayer /// private const int k_QueueSoftMax = 3; + private const float k_MaxQueueTimeDepth = 1.6f; + private ActionRequestData m_PendingSynthesizedAction = new ActionRequestData(); private bool m_HasPendingSynthesizedAction; @@ -36,14 +39,14 @@ public ActionPlayer(ServerCharacter parent) /// public void PlayAction(ref ActionRequestData action) { - if (!action.ShouldQueue) + if (!action.ShouldQueue && m_Queue.Count > 0 && m_Queue[0].Description.ActionInterruptible ) { ClearActions(false); } - if (m_Queue.Count > k_QueueSoftMax && m_Queue[m_Queue.Count - 1].Data.Compare(ref action)) + if( GetQueueTimeDepth() >= k_MaxQueueTimeDepth ) { - //this action is redundant with the last action performed. We simply discard it. + //the queue is too big (in execution seconds) to accommodate any more actions, so this action must be discarded. return; } @@ -265,6 +268,29 @@ private bool UpdateAction(Action action) return keepGoing && !timeExpired; } + /// + /// How much time will it take all remaining Actions in the queue to play out? This sums up all the time each Action is blocking, + /// which is different from each Action's duration. Note that this is an ESTIMATE. An action may block the queue indefinitely if it wishes. + /// + /// The total "time depth" of the queue, or how long it would take to play in seconds, if no more actions were added. + private float GetQueueTimeDepth() + { + if(m_Queue.Count == 0 ) { return 0; } + + float totalTime = 0; + foreach( var action in m_Queue ) + { + var info = action.Description; + float actionTime = info.BlockingMode == BlockingMode.OnlyDuringExecTime ? info.ExecTimeSeconds : + info.BlockingMode == BlockingMode.ExecTimeWithCooldown ? (info.ExecTimeSeconds+info.CooldownSeconds) : + info.BlockingMode == BlockingMode.EntireDuration ? (info.DurationSeconds + info.CooldownSeconds) : + throw new System.Exception($"Unrecognized blocking mode: {info.BlockingMode}"); + totalTime += actionTime; + } + + return totalTime - m_Queue[0].TimeRunning; + } + public void OnCollisionEnter(Collision collision) { if (m_Queue.Count > 0) @@ -273,7 +299,7 @@ public void OnCollisionEnter(Collision collision) } } - /// + /// /// Gives all active Actions a chance to alter a gameplay variable. /// /// diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/FXProjectileTargetedAction.cs b/Assets/BossRoom/Scripts/Server/Game/Action/FXProjectileTargetedAction.cs index d1044adbd..31379f0f6 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/FXProjectileTargetedAction.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/FXProjectileTargetedAction.cs @@ -69,7 +69,7 @@ private bool HasTarget() /// /// Returns our intended target, or null if not found/no target. /// - private ServerCharacter GetTarget() + private IDamageable GetTarget() { if (Data.TargetIds == null || Data.TargetIds.Length == 0) { @@ -79,7 +79,7 @@ private ServerCharacter GetTarget() NetworkObject obj; if (NetworkSpawnManager.SpawnedObjects.TryGetValue(Data.TargetIds[0], out obj) && obj != null) { - return obj.GetComponent(); + return obj.GetComponent(); } else { diff --git a/Assets/BossRoom/Scripts/Server/Game/Character/AIBrain.cs b/Assets/BossRoom/Scripts/Server/Game/Character/AIBrain.cs index 03c316192..b5edacfbd 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Character/AIBrain.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Character/AIBrain.cs @@ -52,6 +52,19 @@ public void Update() m_Logics[m_CurrentState].Update(); } + /// + /// Called when we received some HP. Positive HP is healing, negative is damage. + /// + /// The person who hurt or healed us. May be null. + /// The amount of HP received. Negative is damage. + public void ReceiveHP(ServerCharacter inflicter, int amount) + { + if (inflicter != null && amount < 0) + { + Hate(inflicter); + } + } + private AIStateType FindBestEligibleAIState() { // for now we assume the AI states are in order of appropriateness, diff --git a/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs b/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs index 88b831722..a139caf77 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs @@ -195,6 +195,12 @@ public void ReceiveHP(ServerCharacter inflicter, int HP) NetState.HitPoints = Mathf.Min(NetState.CharacterData.BaseHP.Value, NetState.HitPoints+HP); + if( m_AIBrain != null ) + { + //let the brain know about the modified amount of damage we received. + m_AIBrain.ReceiveHP(inflicter, HP); + } + //we can't currently heal a dead character back to Alive state. //that's handled by a separate function. if (NetState.HitPoints <= 0) diff --git a/Assets/BossRoom/Scripts/Shared/Data/ActionDescription.cs b/Assets/BossRoom/Scripts/Shared/Data/ActionDescription.cs index df2cd14cb..eadcce0a1 100644 --- a/Assets/BossRoom/Scripts/Shared/Data/ActionDescription.cs +++ b/Assets/BossRoom/Scripts/Shared/Data/ActionDescription.cs @@ -65,11 +65,15 @@ public class ActionDescription : ScriptableObject [Tooltip("Prefab to spawn that will manage this action's input")] public BaseActionInput ActionInput; + [Tooltip("Is this Action interruptible by other action plays. Generally, actions with short exec times should not be interruptible in this way.")] + public bool ActionInterruptible; + [System.Serializable] public enum BlockingModeType { EntireDuration, OnlyDuringExecTime, + ExecTimeWithCooldown, } [Tooltip("Indicates how long this action blocks other actions from happening: during the execution stage, or for as long as it runs?")] public BlockingModeType BlockingMode; diff --git a/Assets/BossRoom/Scripts/Shared/Game/Action/ActionRequestData.cs b/Assets/BossRoom/Scripts/Shared/Game/Action/ActionRequestData.cs index 6641353fb..58856d1bd 100644 --- a/Assets/BossRoom/Scripts/Shared/Game/Action/ActionRequestData.cs +++ b/Assets/BossRoom/Scripts/Shared/Game/Action/ActionRequestData.cs @@ -154,6 +154,7 @@ public void NetworkSerialize(NetworkSerializer serializer) { ShouldQueue = (flags & PackFlags.ShouldQueue) != 0; CancelMovement = (flags & PackFlags.CancelMovement) != 0; + ShouldClose = (flags & PackFlags.ShouldClose) != 0; } if ((flags & PackFlags.HasPosition) != 0) diff --git a/Assets/BossRoom/Scripts/Shared/Game/Action/ActionUtils.cs b/Assets/BossRoom/Scripts/Shared/Game/Action/ActionUtils.cs index 28e29d18a..58fcf190f 100644 --- a/Assets/BossRoom/Scripts/Shared/Game/Action/ActionUtils.cs +++ b/Assets/BossRoom/Scripts/Shared/Game/Action/ActionUtils.cs @@ -77,13 +77,8 @@ public static bool IsValidTarget(ulong targetId) return false; } - var targetNetState = targetChar.GetComponent(); - if (targetNetState == null) - { - return false; - } - //only Dead characters are untargetable. All others are - return targetNetState.NetworkLifeState.Value != LifeState.Dead; + var targetable = targetChar.GetComponent(); + return targetable != null && targetable.IsValidTarget; } } diff --git a/Assets/BossRoom/Scripts/Shared/Game/Entity/ITargetable.cs b/Assets/BossRoom/Scripts/Shared/Game/Entity/ITargetable.cs new file mode 100644 index 000000000..674703eba --- /dev/null +++ b/Assets/BossRoom/Scripts/Shared/Game/Entity/ITargetable.cs @@ -0,0 +1,20 @@ +namespace BossRoom +{ + /// + /// Entities that are Targetable by Skills should have their shared NetworkState component implement this interface. + /// + public interface ITargetable + { + /// + /// Is this targetable entity an Npc or a Pc? + /// + bool IsNpc { get; } + + /// + /// Is this Target currently valid. + /// + bool IsValidTarget { get; } + } + +} + diff --git a/Assets/BossRoom/Scripts/Shared/Game/Entity/ITargetable.cs.meta b/Assets/BossRoom/Scripts/Shared/Game/Entity/ITargetable.cs.meta new file mode 100644 index 000000000..d794a3d45 --- /dev/null +++ b/Assets/BossRoom/Scripts/Shared/Game/Entity/ITargetable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1dbddb55b58d45c4c8ddccc1d48c0321 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/BossRoom/Scripts/Shared/Game/Entity/NetworkBreakableState.cs b/Assets/BossRoom/Scripts/Shared/Game/Entity/NetworkBreakableState.cs index 4575a368d..b5dc94b83 100644 --- a/Assets/BossRoom/Scripts/Shared/Game/Entity/NetworkBreakableState.cs +++ b/Assets/BossRoom/Scripts/Shared/Game/Entity/NetworkBreakableState.cs @@ -6,12 +6,16 @@ namespace BossRoom /// /// Shared Network logic for breakable items. /// - public class NetworkBreakableState : NetworkBehaviour + public class NetworkBreakableState : NetworkBehaviour, ITargetable { /// /// Is the item broken or not? /// public NetworkVariableBool IsBroken; + + public bool IsNpc { get { return true; } } + + public bool IsValidTarget { get { return !IsBroken.Value; } } } } diff --git a/Assets/BossRoom/Scripts/Shared/Game/Entity/NetworkCharacterState.cs b/Assets/BossRoom/Scripts/Shared/Game/Entity/NetworkCharacterState.cs index bd1b22612..44a4ef0c0 100644 --- a/Assets/BossRoom/Scripts/Shared/Game/Entity/NetworkCharacterState.cs +++ b/Assets/BossRoom/Scripts/Shared/Game/Entity/NetworkCharacterState.cs @@ -17,7 +17,7 @@ public enum LifeState /// Contains all NetworkVariables and RPCs of a character. This component is present on both client and server objects. /// [RequireComponent(typeof(NetworkHealthState), typeof(NetworkCharacterTypeState))] - public class NetworkCharacterState : NetworkBehaviour, INetMovement + public class NetworkCharacterState : NetworkBehaviour, INetMovement, ITargetable { public void InitNetworkPositionAndRotationY(Vector3 initPosition, float initRotationY) { @@ -97,6 +97,8 @@ public int HitPoints /// public bool IsNpc { get { return CharacterData.IsNpc; } } + public bool IsValidTarget { get { return NetworkLifeState.Value != LifeState.Dead; } } + /// /// The CharacterData object associated with this Character. This is the static game data that defines its attack skills, HP, etc. /// From 74dca7aea71e6c299d3f89df6a50723e02d89f72 Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Wed, 10 Mar 2021 14:39:13 -0500 Subject: [PATCH 02/14] initial changes for action anticipation --- .../Scripts/Client/Game/Action/ActionVisualization.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs b/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs index 602ea6138..aaa581eee 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs @@ -52,6 +52,11 @@ public void OnStoppedChargingUp() } } + public void AnticipateAction(ref ActionRequestData data) + { + + } + public void PlayAction(ref ActionRequestData data) { ActionDescription actionDesc = GameDataSource.Instance.ActionDataByType[data.ActionTypeEnum]; From 40d141e6869abfa62503daec8f8d2c5fa56dcfd6 Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Wed, 10 Mar 2021 15:23:07 -0500 Subject: [PATCH 03/14] more temp work on anticipation --- .../Client/Game/Character/ClientCharacterVisualization.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs b/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs index 7ea5d8a38..1b9cdf9e8 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs @@ -311,5 +311,10 @@ private void ZoomCamera(float scroll) } } } + + public bool IsAnimating() + { + + } } } From 5b5bdf691aa12bbde26962179decda120854e8ba Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Wed, 10 Mar 2021 16:41:29 -0500 Subject: [PATCH 04/14] clearing bogus change to dungeontest --- Assets/BossRoom/Scenes/DungeonTest.unity | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/BossRoom/Scenes/DungeonTest.unity b/Assets/BossRoom/Scenes/DungeonTest.unity index 3ce81f237..890be10c7 100644 --- a/Assets/BossRoom/Scenes/DungeonTest.unity +++ b/Assets/BossRoom/Scenes/DungeonTest.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 oid sha256:a6abed5017c4356c7cd6c39adef5dcf26c36cca1e816f594fd2b26dab5bc64f8 -size 830879 \ No newline at end of file +size 830879 From 0392f8261318ecbb5f7465b173d23cabd2e3ec43 Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Fri, 12 Mar 2021 13:58:04 -0500 Subject: [PATCH 05/14] initial pass at anticipative animations and other responsiveness tweaks --- .../Models/CharacterSetController.controller | 48 ++++----- .../BossRoom/Prefabs/Character/Player.prefab | 4 +- .../Prefabs/{ => FX}/Click_Feedback.prefab | 0 .../{ => FX}/Click_Feedback.prefab.meta | 0 .../Prefabs/FX/fx_SimpleClickFeedback.prefab | 97 +++++++++++++++++++ .../FX/fx_SimpleClickFeedback.prefab.meta | 7 ++ .../BossRoom/Scripts/Client/ClickFeedback.cs | 4 +- .../Scripts/Client/Game/Action/ActionFX.cs | 47 ++++++++- .../Client/Game/Action/ActionVisualization.cs | 70 +++++++++---- .../Game/Action/AnimationOnlyActionFX.cs | 20 +++- .../Scripts/Client/Game/Action/AoeActionFX.cs | 1 + .../Client/Game/Action/ChargedActionFX.cs | 1 + .../Action/FXProjectileTargetedActionFX.cs | 1 + .../Client/Game/Action/MeleeActionFX.cs | 21 +++- .../Client/Game/Action/StealthModeActionFX.cs | 1 + .../Client/Game/Action/TargetActionFX.cs | 26 +++++ .../Client/Game/Action/TrampleActionFX.cs | 1 + .../Character/ClientCharacterVisualization.cs | 41 +++++++- .../Game/Character/ClientInputSender.cs | 25 +++-- .../Scripts/Client/Game/Utils/SelfDisable.cs | 2 + 20 files changed, 355 insertions(+), 62 deletions(-) rename Assets/BossRoom/Prefabs/{ => FX}/Click_Feedback.prefab (100%) rename Assets/BossRoom/Prefabs/{ => FX}/Click_Feedback.prefab.meta (100%) create mode 100644 Assets/BossRoom/Prefabs/FX/fx_SimpleClickFeedback.prefab create mode 100644 Assets/BossRoom/Prefabs/FX/fx_SimpleClickFeedback.prefab.meta diff --git a/Assets/BossRoom/Models/CharacterSetController.controller b/Assets/BossRoom/Models/CharacterSetController.controller index 7eaea27f8..00d7e9026 100644 --- a/Assets/BossRoom/Models/CharacterSetController.controller +++ b/Assets/BossRoom/Models/CharacterSetController.controller @@ -1304,7 +1304,7 @@ AnimatorState: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: NoAttack + m_Name: Nothing m_Speed: 1 m_CycleOffset: 0 m_Transitions: @@ -1491,139 +1491,139 @@ AnimatorController: m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: Attack1 m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: HitReact1 m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: FallDown m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: StandUp m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: BeginRevive m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: Dead m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: ArcherAttack1 m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: Emote1 m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: Emote2 m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: Emote3 m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: Emote4 m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: Trample m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: SkillHeal m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: Stunned m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: Unstunned m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: ShieldBuffStart m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: ShieldBuffEnd m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: ChargedShotStart m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: ChargedShotEnd m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: EntryFainted m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: EntryDead m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} - m_Name: Buff1 m_Type: 9 m_DefaultFloat: 0 m_DefaultInt: 0 m_DefaultBool: 0 - m_Controller: {fileID: 0} + m_Controller: {fileID: 9100000} m_AnimatorLayers: - serializedVersion: 5 m_Name: Base Layer diff --git a/Assets/BossRoom/Prefabs/Character/Player.prefab b/Assets/BossRoom/Prefabs/Character/Player.prefab index a30abe176..8f9f5125d 100644 --- a/Assets/BossRoom/Prefabs/Character/Player.prefab +++ b/Assets/BossRoom/Prefabs/Character/Player.prefab @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 2d0d8ed0724e1404d9d0afcd9b8b5ee2, type: 3} m_Name: m_EditorClassIdentifier: - m_FeedbackPrefab: {fileID: 9137928905311479176, guid: 5d22c1d86e0e5604cbe14004bf924827, type: 3} + m_FeedbackPrefab: {fileID: 9137928905311479176, guid: d526885fdb257c54091f8bdd8fcde277, type: 3} --- !u!114 &2576537793715222015 MonoBehaviour: m_ObjectHideFlags: 0 @@ -59,7 +59,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: Name: - InternalValue: + m_InternalValue: --- !u!1001 &3097905377639811107 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/Assets/BossRoom/Prefabs/Click_Feedback.prefab b/Assets/BossRoom/Prefabs/FX/Click_Feedback.prefab similarity index 100% rename from Assets/BossRoom/Prefabs/Click_Feedback.prefab rename to Assets/BossRoom/Prefabs/FX/Click_Feedback.prefab diff --git a/Assets/BossRoom/Prefabs/Click_Feedback.prefab.meta b/Assets/BossRoom/Prefabs/FX/Click_Feedback.prefab.meta similarity index 100% rename from Assets/BossRoom/Prefabs/Click_Feedback.prefab.meta rename to Assets/BossRoom/Prefabs/FX/Click_Feedback.prefab.meta diff --git a/Assets/BossRoom/Prefabs/FX/fx_SimpleClickFeedback.prefab b/Assets/BossRoom/Prefabs/FX/fx_SimpleClickFeedback.prefab new file mode 100644 index 000000000..57985f3c2 --- /dev/null +++ b/Assets/BossRoom/Prefabs/FX/fx_SimpleClickFeedback.prefab @@ -0,0 +1,97 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &9137928905311479176 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2500332623759108304} + - component: {fileID: 6101625250476277925} + - component: {fileID: 6375111725193425194} + - component: {fileID: 5754560017040867806} + m_Layer: 0 + m_Name: fx_SimpleClickFeedback + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2500332623759108304 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9137928905311479176} + m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 2.5, y: 2.5, z: 2.5} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} +--- !u!33 &6101625250476277925 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9137928905311479176} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &6375111725193425194 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9137928905311479176} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: bfad40b971740ef4381f47a69fd3348d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &5754560017040867806 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9137928905311479176} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b853e11fb193c8149bd7d25b17c0ddc6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DisabledDelay: 0.75 diff --git a/Assets/BossRoom/Prefabs/FX/fx_SimpleClickFeedback.prefab.meta b/Assets/BossRoom/Prefabs/FX/fx_SimpleClickFeedback.prefab.meta new file mode 100644 index 000000000..00c3e5448 --- /dev/null +++ b/Assets/BossRoom/Prefabs/FX/fx_SimpleClickFeedback.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d526885fdb257c54091f8bdd8fcde277 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/BossRoom/Scripts/Client/ClickFeedback.cs b/Assets/BossRoom/Scripts/Client/ClickFeedback.cs index 3a73121bf..6d4d5a580 100644 --- a/Assets/BossRoom/Scripts/Client/ClickFeedback.cs +++ b/Assets/BossRoom/Scripts/Client/ClickFeedback.cs @@ -27,7 +27,7 @@ void Start() } m_ClientSender = GetComponent(); - m_ClientSender.OnClientClick += onClick; + m_ClientSender.ClientMoveEvent += onClick; m_FeedbackObj = Instantiate(m_FeedbackPrefab); m_FeedbackObj.SetActive(false); } @@ -44,7 +44,7 @@ private void OnDestroy() { if (m_ClientSender) { - m_ClientSender.OnClientClick -= onClick; + m_ClientSender.ClientMoveEvent -= onClick; } } } diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs index 15b324fdd..86ee61067 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs @@ -8,6 +8,11 @@ public abstract class ActionFX : ActionBase { protected ClientCharacterVisualization m_Parent; + /// + /// True if this actionFX began running immediately, prior to getting a confirmation from the server. + /// + public bool Anticipated { get; protected set; } + public ActionFX(ref ActionRequestData data, ClientCharacterVisualization parent) : base(ref data) { m_Parent = parent; @@ -16,8 +21,15 @@ public ActionFX(ref ActionRequestData data, ClientCharacterVisualization parent) /// /// Starts the ActionFX. Derived classes may return false if they wish to end immediately without their Update being called. /// + /// + /// Derived class should be sure to call base.Start() in their implementation, but note that this resets "Anticipated" to false. + /// /// true to play, false to be immediately cleaned up. - public abstract bool Start(); + public virtual bool Start() + { + Anticipated = false; //once you start for real you are no longer an anticipated action. + return true; + } public abstract bool Update(); @@ -49,17 +61,48 @@ public static ActionFX MakeActionFX(ref ActionRequestData data, ClientCharacterV case ActionLogic.RangedFXTargeted: return new FXProjectileTargetedActionFX(ref data, parent); case ActionLogic.Trample: return new TrampleActionFX(ref data, parent); case ActionLogic.AoE: return new AoeActionFX(ref data, parent); - case ActionLogic.Stunned: return new AnimationOnlyActionFX(ref data, parent); case ActionLogic.Target: return new TargetActionFX(ref data, parent); + case ActionLogic.ChargedShield: case ActionLogic.ChargedLaunchProjectile: return new ChargedActionFX(ref data, parent); + case ActionLogic.StealthMode: return new StealthModeActionFX(ref data, parent); + + case ActionLogic.Stunned: + case ActionLogic.LaunchProjectile: + case ActionLogic.Revive: + case ActionLogic.Emote: return new AnimationOnlyActionFX(ref data, parent); + default: throw new System.NotImplementedException(); } } + /// + /// Should this ActionFX be created anticipatively on the owning client? + /// + /// The request being sent to the server + /// If true ActionVisualization should pre-emptively create the ActionFX on the owning client, before hearing back from the server. + public static bool ShouldAnticipate(ref ActionRequestData data) + { + var actionLogic = GameDataSource.Instance.ActionDataByType[data.ActionTypeEnum].Logic; + + //at present all Actionts anticipate except for the Target action, which runs a single instance on the client and is + //responsible for action anticipation on its own. + return actionLogic != ActionLogic.Target; + } + public virtual void OnAnimEvent(string id) { } public virtual void OnStoppedChargingUp() { } + + /// + /// Called when the action is being "anticipated" on the client. For example, if you are the owner of a tank and you swing your hammer, + /// you get this call immediately on the client, before the server round-trip. + /// Overriders should always call the base class in their implementation! + /// + public virtual void AnticipateAction() + { + Anticipated = true; + } } } diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs b/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs index aaa581eee..ac7820282 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs @@ -9,14 +9,19 @@ namespace BossRoom.Visual /// public class ActionVisualization { - private List m_PlayingActions; + private List m_PlayingActions = new List(); + + /// + /// Don't let anticipated actionFXs persist longer than this. This is a safeguard against scenarios + /// where we never get a confirmed action for an action we anticipated. + /// + private const float k_AnticipationTimeoutSeconds = 1; public ClientCharacterVisualization Parent { get; private set; } public ActionVisualization(ClientCharacterVisualization parent) { Parent = parent; - m_PlayingActions = new List(); } public void Update() @@ -27,15 +32,24 @@ public void Update() var action = m_PlayingActions[i]; bool keepGoing = action.Update(); bool expirable = action.Description.DurationSeconds > 0f; //non-positive value is a sentinel indicating the duration is indefinite. - bool timeExpired = expirable && (Time.time - action.TimeStarted) >= action.Description.DurationSeconds; - if (!keepGoing || timeExpired) + bool timeExpired = expirable && action.TimeRunning >= action.Description.DurationSeconds; + bool timedOut = action.Anticipated && action.TimeRunning >= k_AnticipationTimeoutSeconds; + if (!keepGoing || timeExpired || timedOut) { - action.End(); + if (timedOut) { action.Cancel(); } //an anticipated action that timed out shouldn't get its End called. It is canceled instead. + else { action.End(); } + m_PlayingActions.RemoveAt(i); } } } + //helper wrapper for a FindIndex call on m_PlayingActions. + private int FindAction(ActionType action ) + { + return m_PlayingActions.FindIndex(a => a.Description.ActionTypeEnum == action); + } + public void OnAnimEvent(string id) { foreach (var actionFX in m_PlayingActions) @@ -52,26 +66,42 @@ public void OnStoppedChargingUp() } } + /// + /// Called on the client that owns the Character when the player triggers an action. This allows actions to immediately start playing feedback. + /// + /// + /// An important concept of Action Anticipation is that it is opportunistic--it doesn't make any strong guarantees. You don't get an anticipated + /// action animation if you are already animating in some way, as one example. Another complexity is that you don't know if the server will actually + /// let you play all the actions that you've requested--some may get thrown away, e.g. because you have too many actions in your queue. What this means + /// is that Anticipated Actions (actions that have been constructed but not started) won't match up perfectly with actual approved delivered actions from + /// the server. For that reason, it must always be fine to receive PlayAction and not have an anticipated action already started (this is true for playback + /// Characters belonging to the server and other characters anyway). It also means we need to handle the case where we created an Anticipated Action, but + /// never got a confirmation--actions like that need to eventually get discarded. + /// + /// Current limitations: + /// * the only anticipation performed is to play an animation. + /// * Individual Actions might need to implement their own sophisticated Anticipation logic. For example, LaunchProjectile could actually create the projectile + /// and start it moving along its expected path, and then somehow link up its purely visual projectile with the real networked projectile that the server + /// eventually creates. + /// + /// The Action that is being requested. + public void AnticipateAction(ref ActionRequestData data) { - + if (!Parent.IsAnimating && ActionFX.ShouldAnticipate(ref data)) + { + var actionFX = ActionFX.MakeActionFX(ref data, Parent); + actionFX.TimeStarted = Time.time; + actionFX.AnticipateAction(); + m_PlayingActions.Add(actionFX); + } } public void PlayAction(ref ActionRequestData data) { - ActionDescription actionDesc = GameDataSource.Instance.ActionDataByType[data.ActionTypeEnum]; + var anticipatedActionIndex = FindAction(data.ActionTypeEnum); - //Do Trivial Actions (actions that just require playing a single animation, and don't require any state tracking). - switch (actionDesc.Logic) - { - case ActionLogic.LaunchProjectile: - case ActionLogic.Revive: - case ActionLogic.Emote: - Parent.OurAnimator.SetTrigger(actionDesc.Anim); - return; - } - - var actionFX = ActionFX.MakeActionFX(ref data, Parent); + var actionFX = anticipatedActionIndex>=0 ? m_PlayingActions[anticipatedActionIndex] : ActionFX.MakeActionFX(ref data, Parent); actionFX.TimeStarted = Time.time; if (actionFX.Start()) { @@ -90,7 +120,7 @@ public void CancelAllActions() public void CancelAllActionsOfType(ActionType actionType) { - for (int i = m_PlayingActions.Count-1; i >=0; --i) + for (int i = m_PlayingActions.Count - 1; i >= 0; --i) { if (m_PlayingActions[i].Description.ActionTypeEnum == actionType) { @@ -105,7 +135,7 @@ public void CancelAllActionsOfType(ActionType actionType) /// public void CancelAll() { - foreach( var action in m_PlayingActions ) + foreach (var action in m_PlayingActions) { action.Cancel(); } diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/AnimationOnlyActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/AnimationOnlyActionFX.cs index 5840262de..d25db4b7c 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/AnimationOnlyActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/AnimationOnlyActionFX.cs @@ -13,16 +13,32 @@ public AnimationOnlyActionFX(ref ActionRequestData data, ClientCharacterVisualiz public override bool Start() { - m_Parent.OurAnimator.SetTrigger(Description.Anim); + if( !Anticipated ) + { + PlayStartAnim(); + } + + base.Start(); return true; } + private void PlayStartAnim() + { + m_Parent.OurAnimator.SetTrigger(Description.Anim); + } + + public override void AnticipateAction() + { + base.AnticipateAction(); + PlayStartAnim(); + } + public override bool Update() { return ActionConclusion.Continue; } - public override void End() + public override void Cancel() { if (!string.IsNullOrEmpty(Description.Anim2)) { diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/AoeActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/AoeActionFX.cs index 706aae884..29319e32b 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/AoeActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/AoeActionFX.cs @@ -11,6 +11,7 @@ public AoeActionFX(ref ActionRequestData data, ClientCharacterVisualization pare public override bool Start() { + base.Start(); m_Parent.OurAnimator.SetTrigger(Description.Anim); var actionDescription = GameDataSource.Instance.ActionDataByType[m_Data.ActionTypeEnum]; var vfxObject = GameObject.Instantiate(actionDescription.Spawns[0], m_Data.Position, Quaternion.identity); diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/ChargedActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/ChargedActionFX.cs index 96aeaf7cd..744c23628 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/ChargedActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/ChargedActionFX.cs @@ -27,6 +27,7 @@ public ChargedActionFX(ref ActionRequestData data, ClientCharacterVisualization public override bool Start() { + base.Start(); m_Parent.OurAnimator.SetTrigger(Description.Anim); if (Description.Spawns.Length > 0) diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs index 3e9b41e9f..e1d09061a 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs @@ -25,6 +25,7 @@ public FXProjectileTargetedActionFX(ref ActionRequestData data, ClientCharacterV public override bool Start() { + base.Start(); m_Target = GetTarget(); if (HasTarget() && m_Target == null) { diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/MeleeActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/MeleeActionFX.cs index 5673c57c1..941e42d29 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/MeleeActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/MeleeActionFX.cs @@ -21,7 +21,12 @@ public MeleeActionFX(ref ActionRequestData data, ClientCharacterVisualization pa public override bool Start() { - m_Parent.OurAnimator.SetTrigger(Description.Anim); + if( !Anticipated) + { + PlayAnim(); + } + + base.Start(); return true; } @@ -45,6 +50,11 @@ public override void End() PlayHitReact(); } + private void PlayAnim() + { + m_Parent.OurAnimator.SetTrigger(Description.Anim); + } + private void PlayHitReact() { if (m_ImpactPlayed) { return; } @@ -74,5 +84,14 @@ private void PlayHitReact() //in the future we may do another physics check to handle the case where a target "ran under our weapon". //But for now, if the original target is no longer present, then we just don't play our hit react on anything. } + + public override void AnticipateAction() + { + base.AnticipateAction(); + + //note: because the hit-react is driven from the animation, this means we can anticipatively trigger a hit-react too. That + //will make combat feel responsive, but of course the actual damage won't be applied until the server tells us about it. + PlayAnim(); + } } } diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/StealthModeActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/StealthModeActionFX.cs index 2f76ba430..917eae680 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/StealthModeActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/StealthModeActionFX.cs @@ -27,6 +27,7 @@ public StealthModeActionFX(ref ActionRequestData data, ClientCharacterVisualizat public override bool Start() { + base.Start(); m_Parent.OurAnimator.SetTrigger(Description.Anim); return true; } diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs index 8e44e0d5f..11008d23b 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs @@ -13,6 +13,7 @@ public class TargetActionFX : ActionFX { private GameObject m_TargetReticule; private ulong m_CurrentTarget; + private ulong m_NewTarget; private NetworkCharacterState m_ParentState; private const float k_ReticuleGroundHeight = 0.2f; @@ -23,10 +24,29 @@ public TargetActionFX(ref ActionRequestData data, ClientCharacterVisualization p public override bool Start() { + base.Start(); m_ParentState = m_Parent.Parent.GetComponent(); + + m_ParentState.TargetId.OnValueChanged += OnTargetChanged; + m_ParentState.GetComponent().ActionInputEvent += OnActionInput; + return true; } + private void OnTargetChanged(ulong oldTarget, ulong newTarget ) + { + m_NewTarget = newTarget; + } + + private void OnActionInput(ActionRequestData data ) + { + //this method runs on the owning client, and allows us to anticipate our new target for purposes of FX visualization. + if( data.ActionTypeEnum == ActionType.GeneralTarget ) + { + m_NewTarget = data.TargetIds[0]; + } + } + public override bool Update() { if( m_CurrentTarget != m_ParentState.TargetId.Value ) @@ -85,6 +105,12 @@ private void ValidateReticule(NetworkObject targetObject) public override void Cancel() { GameObject.Destroy(m_TargetReticule); + + m_ParentState.TargetId.OnValueChanged -= OnTargetChanged; + if( m_ParentState.TryGetComponent(out Client.ClientInputSender inputSender)) + { + inputSender.ActionInputEvent -= OnActionInput; + } } } diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/TrampleActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/TrampleActionFX.cs index def39ff0d..bfd36086c 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/TrampleActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/TrampleActionFX.cs @@ -37,6 +37,7 @@ public TrampleActionFX(ref ActionRequestData data, ClientCharacterVisualization public override bool Start() { + base.Start(); m_Parent.OurAnimator.SetTrigger(Description.Anim); return true; } diff --git a/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs b/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs index 1b9cdf9e8..8787c6b4c 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs @@ -2,8 +2,6 @@ using Cinemachine; using MLAPI; using System; -using System.Collections; -using System.ComponentModel; using UnityEngine; namespace BossRoom.Visual @@ -122,6 +120,12 @@ public override void NetworkStart() m_ActionViz.PlayAction(ref data); AttachCamera(); m_PartyHUD.SetHeroData(m_NetState); + + if( Parent.TryGetComponent(out ClientInputSender inputSender)) + { + inputSender.ActionInputEvent += OnActionInput; + inputSender.ClientMoveEvent += OnMoveInput; + } } else { @@ -131,6 +135,19 @@ public override void NetworkStart() } } + private void OnActionInput(ActionRequestData data) + { + m_ActionViz.AnticipateAction(ref data); + } + + private void OnMoveInput(Vector3 position) + { + if( !IsAnimating ) + { + OurAnimator.SetTrigger("AnticipateMove"); + } + } + /// /// The switch to certain LifeStates fires an animation on an NPC/PC. This bypasses that initial animation /// and sends an NPC/PC to their eventual looping animation. This is necessary for mid-game player connections. @@ -159,6 +176,12 @@ private void OnDestroy() m_NetState.OnPerformHitReaction -= OnPerformHitReaction; m_NetState.OnStopChargingUpClient -= OnStoppedChargingUp; m_NetState.IsStealthy.OnValueChanged -= OnStealthyChanged; + + if (Parent != null && Parent.TryGetComponent(out ClientInputSender sender)) + { + sender.ActionInputEvent -= OnActionInput; + sender.ClientMoveEvent -= OnMoveInput; + } } } @@ -312,9 +335,21 @@ private void ZoomCamera(float scroll) } } - public bool IsAnimating() + public bool IsAnimating { + get + { + //layer 0 is our movement layer, and has a special base state. + bool animating = !OurAnimator.GetCurrentAnimatorStateInfo(0).IsName("WalkRun") || OurAnimator.GetFloat("Speed") > 0.0; + if (animating) { return false; } + for (int i = 1; i < OurAnimator.layerCount; i++) + { + if (!OurAnimator.GetCurrentAnimatorStateInfo(i).IsName("Nothing")) { return true; } + } + + return false; + } } } } diff --git a/Assets/BossRoom/Scripts/Client/Game/Character/ClientInputSender.cs b/Assets/BossRoom/Scripts/Client/Game/Character/ClientInputSender.cs index d2c1b3c92..81635d4cf 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Character/ClientInputSender.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Character/ClientInputSender.cs @@ -16,7 +16,9 @@ public class ClientInputSender : NetworkBehaviour { private const float k_MouseInputRaycastDistance = 100f; - private const float k_MoveSendRateSeconds = 0.5f; + private const float k_MoveSendRateSeconds = 0.05f; //20 fps. + + private const float k_TargetMoveTimeout = 0.45f; //prevent moves for this long after targeting someone (helps prevent walking to the guy you clicked). private float m_LastSentMove; @@ -29,6 +31,11 @@ public class ClientInputSender : NetworkBehaviour private NetworkCharacterState m_NetworkCharacter; + /// + /// This event fires at the time when an action request is sent to the server. + /// + public Action ActionInputEvent; + /// /// This describes how a skill was requested. Skills requested via mouse click will do raycasts to determine their target; skills requested /// in other matters will use the stateful target stored in NetworkCharacterState. @@ -73,7 +80,7 @@ private struct ActionRequest Camera m_MainCamera; - public event Action OnClientClick; + public event Action ClientMoveEvent; /// /// Convenience getter that returns our CharacterData @@ -156,10 +163,11 @@ void FixedUpdate() var ray = m_MainCamera.ScreenPointToRay(Input.mousePosition); if (Physics.RaycastNonAlloc(ray, k_CachedHit, k_MouseInputRaycastDistance, k_GroundLayerMask) > 0) { - // The MLAPI_INTERNAL channel is a reliable sequenced channel. Inputs should always arrive and be in order that's why this channel is used. - m_NetworkCharacter.SendCharacterInputServerRpc(k_CachedHit[0].point); + // The MLAPI_INTERNAL channel is a reliable sequenced channel. Inputs should always arrive and be in order that's why this channel is used. + m_NetworkCharacter.SendCharacterInputServerRpc(k_CachedHit[0].point); + //Send our client only click request - OnClientClick?.Invoke(k_CachedHit[0].point); + ClientMoveEvent?.Invoke(k_CachedHit[0].point); } } } @@ -193,7 +201,9 @@ private void PerformSkill(ActionType actionType, SkillTriggerStyle triggerStyle) if (GetActionRequestForTarget(hitTransform, actionType, triggerStyle, out ActionRequestData playerAction)) { //Don't trigger our move logic for another 500ms. This protects us from moving just because we clicked on them to target them. - m_LastSentMove = Time.time; + m_LastSentMove = Time.time + k_TargetMoveTimeout; + + ActionInputEvent?.Invoke(playerAction); m_NetworkCharacter.RecvDoActionServerRPC(playerAction); } else if(actionType != ActionType.GeneralTarget ) @@ -201,7 +211,10 @@ private void PerformSkill(ActionType actionType, SkillTriggerStyle triggerStyle) // clicked on nothing... perform a "miss" attack on the spot they clicked on var data = new ActionRequestData(); PopulateSkillRequest(k_CachedHit[0].point, actionType, ref data); + + ActionInputEvent?.Invoke(data); m_NetworkCharacter.RecvDoActionServerRPC(data); + } } diff --git a/Assets/BossRoom/Scripts/Client/Game/Utils/SelfDisable.cs b/Assets/BossRoom/Scripts/Client/Game/Utils/SelfDisable.cs index 8dbd289dd..affc8ee38 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Utils/SelfDisable.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Utils/SelfDisable.cs @@ -14,6 +14,7 @@ void Update() { if (Time.time >= m_DisableTimestamp) { + Debug.Log($"Click Feedback disabling at {Time.time}"); gameObject.SetActive(false); } } @@ -21,5 +22,6 @@ void Update() void OnEnable() { m_DisableTimestamp = Time.time + m_DisabledDelay; + Debug.Log($"Enabling Click Feedback at: {Time.time}, will disable at {m_DisableTimestamp}"); } } From 7d8219cf5fb8f484894143392aae1a915f55f0ef Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Mon, 15 Mar 2021 15:16:45 -0400 Subject: [PATCH 06/14] fixing compilation isue --- Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs b/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs index fb7088317..ffcb519a6 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs @@ -22,8 +22,6 @@ public class ActionPlayer /// private const float k_MaxQueueTimeDepth = 1.6f; - private const float k_MaxQueueTimeDepth = 1.6f; - private ActionRequestData m_PendingSynthesizedAction = new ActionRequestData(); private bool m_HasPendingSynthesizedAction; From ee13f39c03f137a623046f36e72cd17080d879d0 Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Mon, 15 Mar 2021 15:54:29 -0400 Subject: [PATCH 07/14] iterating on controller and restoring click feedback --- .../CharacterSetController.controller | 86 ++++++++- .../BossRoom/Prefabs/Character/Player.prefab | 108 ++++------- Assets/BossRoom/Prefabs/Click_Feedback.prefab | 175 ++++++++++++++++++ .../Prefabs/Click_Feedback.prefab.meta | 7 + 4 files changed, 303 insertions(+), 73 deletions(-) create mode 100644 Assets/BossRoom/Prefabs/Click_Feedback.prefab create mode 100644 Assets/BossRoom/Prefabs/Click_Feedback.prefab.meta diff --git a/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller b/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller index 26bc7adda..0cce4f333 100644 --- a/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller +++ b/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller @@ -754,6 +754,28 @@ AnimatorStateTransition: m_InterruptionSource: 0 m_OrderedInterruption: 1 m_CanTransitionToSelf: 1 +--- !u!1101 &-4504660523056349306 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: [] + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: -3516404760485336223} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 0 + serializedVersion: 3 + m_TransitionDuration: 0 + m_TransitionOffset: 0.0020768787 + m_ExitTime: 1 + m_HasExitTime: 1 + m_HasFixedDuration: 1 + m_InterruptionSource: 0 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 --- !u!1102 &-4482486829903005221 AnimatorState: serializedVersion: 6 @@ -954,6 +976,7 @@ AnimatorState: - {fileID: -1751189744513987592} - {fileID: -3322349416516825559} - {fileID: 5808351605165405389} + - {fileID: 2324578261836027962} m_StateMachineBehaviours: [] m_Position: {x: 50, y: 50, z: 0} m_IKOnFeet: 0 @@ -1316,7 +1339,7 @@ AnimatorState: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: NoAttack + m_Name: Nothing m_Speed: 1 m_CycleOffset: 0 m_Transitions: @@ -1401,6 +1424,9 @@ AnimatorStateMachine: - serializedVersion: 1 m_State: {fileID: 7103618770137260043} m_Position: {x: -350, y: 330, z: 0} + - serializedVersion: 1 + m_State: {fileID: 1876505395603539253} + m_Position: {x: 290, y: 310, z: 0} m_ChildStateMachines: [] m_AnyStateTransitions: - {fileID: 6300214233644051234} @@ -1637,6 +1663,12 @@ AnimatorController: m_DefaultInt: 0 m_DefaultBool: 0 m_Controller: {fileID: 0} + - m_Name: AnticipateMove + m_Type: 9 + m_DefaultFloat: 0 + m_DefaultInt: 0 + m_DefaultBool: 0 + m_Controller: {fileID: 0} m_AnimatorLayers: - serializedVersion: 5 m_Name: Base Layer @@ -1807,6 +1839,33 @@ AnimatorStateTransition: m_InterruptionSource: 0 m_OrderedInterruption: 1 m_CanTransitionToSelf: 1 +--- !u!1102 &1876505395603539253 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: AnticipateMove + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: + - {fileID: -4504660523056349306} + m_StateMachineBehaviours: [] + m_Position: {x: 50, y: 50, z: 0} + m_IKOnFeet: 0 + m_WriteDefaultValues: 1 + m_Mirror: 0 + m_SpeedParameterActive: 0 + m_MirrorParameterActive: 0 + m_CycleOffsetParameterActive: 0 + m_TimeParameterActive: 0 + m_Motion: {fileID: -4428684883894617094, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: --- !u!1101 &1916661995635438397 AnimatorStateTransition: m_ObjectHideFlags: 1 @@ -1859,6 +1918,31 @@ AnimatorState: m_MirrorParameter: m_CycleOffsetParameter: m_TimeParameter: +--- !u!1101 &2324578261836027962 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: + - m_ConditionMode: 1 + m_ConditionEvent: AnticipateMove + m_EventTreshold: 0 + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: 1876505395603539253} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 0 + serializedVersion: 3 + m_TransitionDuration: 0 + m_TransitionOffset: 0 + m_ExitTime: 1.2550513e-10 + m_HasExitTime: 0 + m_HasFixedDuration: 1 + m_InterruptionSource: 0 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 --- !u!1101 &2356557320833519340 AnimatorStateTransition: m_ObjectHideFlags: 1 diff --git a/Assets/BossRoom/Prefabs/Character/Player.prefab b/Assets/BossRoom/Prefabs/Character/Player.prefab index 05bc319f4..652270524 100644 --- a/Assets/BossRoom/Prefabs/Character/Player.prefab +++ b/Assets/BossRoom/Prefabs/Character/Player.prefab @@ -12,8 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 2d0d8ed0724e1404d9d0afcd9b8b5ee2, type: 3} m_Name: m_EditorClassIdentifier: - m_FeedbackPrefab: {fileID: 9137928905311479176, guid: d526885fdb257c54091f8bdd8fcde277, - type: 3} + m_FeedbackPrefab: {fileID: 9137928905311479176, guid: 5d22c1d86e0e5604cbe14004bf924827, type: 3} --- !u!114 &2576537793715222015 MonoBehaviour: m_ObjectHideFlags: 0 @@ -28,8 +27,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_DisplayHealth: 1 m_DisplayName: 1 - m_UIStatePrefab: {fileID: -1943162842029199943, guid: 2b07482491a17964380023240087ce16, - type: 3} + m_UIStatePrefab: {fileID: -1943162842029199943, guid: 2b07482491a17964380023240087ce16, type: 3} m_NetworkNameState: {fileID: 8169487339863708723} m_NetworkHealthState: {fileID: 7751377510591478590} m_BaseHP: {fileID: 0} @@ -70,63 +68,51 @@ PrefabInstance: m_Modification: m_TransformParent: {fileID: 6009713983291384766} m_Modifications: - - target: {fileID: 3736552308919084700, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 3736552308919084700, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_Name value: PlayerGraphics objectReference: {fileID: 0} - - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_RootOrder value: 0 objectReference: {fileID: 0} - - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_LocalPosition.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_LocalPosition.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_LocalPosition.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_LocalRotation.w value: 1 objectReference: {fileID: 0} - - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_LocalRotation.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_LocalRotation.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_LocalRotation.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_LocalEulerAnglesHint.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + - target: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} @@ -134,8 +120,7 @@ PrefabInstance: m_SourcePrefab: {fileID: 100100000, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} --- !u!4 &1327663231359497221 stripped Transform: - m_CorrespondingSourceObject: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, - type: 3} + m_CorrespondingSourceObject: {fileID: 4076098699203836966, guid: d396ab139e993ee43b2eb29978bba8ff, type: 3} m_PrefabInstance: {fileID: 3097905377639811107} m_PrefabAsset: {fileID: 0} --- !u!1001 &7831782662127126385 @@ -145,89 +130,71 @@ PrefabInstance: m_Modification: m_TransformParent: {fileID: 0} m_Modifications: - - target: {fileID: 4600110157238723776, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723776, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_AoePrefab value: - objectReference: {fileID: 8447158110562487606, guid: 88beb3857541f46d9becf14ba3392b89, - type: 3} - - target: {fileID: 4600110157238723777, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + objectReference: {fileID: 8447158110562487606, guid: 88beb3857541f46d9becf14ba3392b89, type: 3} + - target: {fileID: 4600110157238723777, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_NetworkNameState value: objectReference: {fileID: 8169487339863708723} - - target: {fileID: 4600110157238723777, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723777, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_NetworkNameTagState value: objectReference: {fileID: 8169487339863708723} - - target: {fileID: 4600110157238723781, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723781, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_Name value: Player objectReference: {fileID: 0} - - target: {fileID: 4600110157238723790, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723790, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: PrefabHash value: 1897319656204293034 objectReference: {fileID: 0} - - target: {fileID: 4600110157238723790, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723790, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: PrefabHashGenerator value: Player objectReference: {fileID: 0} - - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_RootOrder value: 0 objectReference: {fileID: 0} - - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_LocalPosition.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_LocalPosition.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_LocalPosition.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_LocalRotation.w value: 1 objectReference: {fileID: 0} - - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_LocalRotation.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_LocalRotation.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_LocalRotation.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_LocalEulerAnglesHint.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + - target: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} @@ -235,20 +202,17 @@ PrefabInstance: m_SourcePrefab: {fileID: 100100000, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} --- !u!1 &6009713983291384756 stripped GameObject: - m_CorrespondingSourceObject: {fileID: 4600110157238723781, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + m_CorrespondingSourceObject: {fileID: 4600110157238723781, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} m_PrefabInstance: {fileID: 7831782662127126385} m_PrefabAsset: {fileID: 0} --- !u!4 &6009713983291384766 stripped Transform: - m_CorrespondingSourceObject: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + m_CorrespondingSourceObject: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} m_PrefabInstance: {fileID: 7831782662127126385} m_PrefabAsset: {fileID: 0} --- !u!114 &7751377510591478590 stripped MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 514105321093282895, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, - type: 3} + m_CorrespondingSourceObject: {fileID: 514105321093282895, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3} m_PrefabInstance: {fileID: 7831782662127126385} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6009713983291384756} diff --git a/Assets/BossRoom/Prefabs/Click_Feedback.prefab b/Assets/BossRoom/Prefabs/Click_Feedback.prefab new file mode 100644 index 000000000..bbd64d23b --- /dev/null +++ b/Assets/BossRoom/Prefabs/Click_Feedback.prefab @@ -0,0 +1,175 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &9137928905311479176 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2500332623759108304} + - component: {fileID: 6101625250476277925} + - component: {fileID: 6375111725193425194} + - component: {fileID: 7164482062141736850} + - component: {fileID: 5754560017040867806} + m_Layer: 0 + m_Name: Click_Feedback + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2500332623759108304 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9137928905311479176} + m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2816127936030266596} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} +--- !u!33 &6101625250476277925 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9137928905311479176} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &6375111725193425194 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9137928905311479176} + m_Enabled: 0 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!64 &7164482062141736850 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9137928905311479176} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 4 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!114 &5754560017040867806 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9137928905311479176} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b853e11fb193c8149bd7d25b17c0ddc6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DisabledDelay: 0.75 +--- !u!1001 &5569208290851949093 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 2500332623759108304} + m_Modifications: + - target: {fileID: 6957808770263120477, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_Name + value: GroundClickFX + objectReference: {fileID: 0} + - target: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} +--- !u!4 &2816127936030266596 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 7664326125434658497, guid: 7c2bd7eca3b96084f99aa3a945102b11, type: 3} + m_PrefabInstance: {fileID: 5569208290851949093} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/BossRoom/Prefabs/Click_Feedback.prefab.meta b/Assets/BossRoom/Prefabs/Click_Feedback.prefab.meta new file mode 100644 index 000000000..538f39f7d --- /dev/null +++ b/Assets/BossRoom/Prefabs/Click_Feedback.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5d22c1d86e0e5604cbe14004bf924827 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From bfad6325bc2ad512df3b2660aa804bc65c5b6973 Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Mon, 15 Mar 2021 17:48:24 -0400 Subject: [PATCH 08/14] more iteration on animations --- .../CharacterSetController.controller | 154 +++++++++--------- ...acterSetController_Tank.overrideController | 2 + .../Server/Game/Character/ServerCharacter.cs | 1 + 3 files changed, 80 insertions(+), 77 deletions(-) diff --git a/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller b/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller index 0cce4f333..f0aad7ba3 100644 --- a/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller +++ b/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller @@ -754,28 +754,6 @@ AnimatorStateTransition: m_InterruptionSource: 0 m_OrderedInterruption: 1 m_CanTransitionToSelf: 1 ---- !u!1101 &-4504660523056349306 -AnimatorStateTransition: - m_ObjectHideFlags: 1 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: - m_Conditions: [] - m_DstStateMachine: {fileID: 0} - m_DstState: {fileID: -3516404760485336223} - m_Solo: 0 - m_Mute: 0 - m_IsExit: 0 - serializedVersion: 3 - m_TransitionDuration: 0 - m_TransitionOffset: 0.0020768787 - m_ExitTime: 1 - m_HasExitTime: 1 - m_HasFixedDuration: 1 - m_InterruptionSource: 0 - m_OrderedInterruption: 1 - m_CanTransitionToSelf: 1 --- !u!1102 &-4482486829903005221 AnimatorState: serializedVersion: 6 @@ -976,7 +954,7 @@ AnimatorState: - {fileID: -1751189744513987592} - {fileID: -3322349416516825559} - {fileID: 5808351605165405389} - - {fileID: 2324578261836027962} + - {fileID: 426919566368059880} m_StateMachineBehaviours: [] m_Position: {x: 50, y: 50, z: 0} m_IKOnFeet: 0 @@ -1425,8 +1403,8 @@ AnimatorStateMachine: m_State: {fileID: 7103618770137260043} m_Position: {x: -350, y: 330, z: 0} - serializedVersion: 1 - m_State: {fileID: 1876505395603539253} - m_Position: {x: 290, y: 310, z: 0} + m_State: {fileID: 7052821593652808675} + m_Position: {x: 370, y: 290, z: 0} m_ChildStateMachines: [] m_AnyStateTransitions: - {fileID: 6300214233644051234} @@ -1516,6 +1494,28 @@ AnimatorState: m_MirrorParameter: m_CycleOffsetParameter: m_TimeParameter: +--- !u!1101 &-97121490881636740 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: [] + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: -3516404760485336223} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 0 + serializedVersion: 3 + m_TransitionDuration: 0.62071574 + m_TransitionOffset: 0.00000004339141 + m_ExitTime: 0.0000000041531494 + m_HasExitTime: 1 + m_HasFixedDuration: 0 + m_InterruptionSource: 2 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 --- !u!91 &9100000 AnimatorController: m_ObjectHideFlags: 0 @@ -1753,6 +1753,31 @@ AnimatorStateTransition: m_InterruptionSource: 0 m_OrderedInterruption: 1 m_CanTransitionToSelf: 1 +--- !u!1101 &426919566368059880 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: + - m_ConditionMode: 1 + m_ConditionEvent: AnticipateMove + m_EventTreshold: 0 + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: 7052821593652808675} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 0 + serializedVersion: 3 + m_TransitionDuration: 0.118838675 + m_TransitionOffset: 0 + m_ExitTime: 0.03151326 + m_HasExitTime: 0 + m_HasFixedDuration: 0 + m_InterruptionSource: 2 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 --- !u!114 &462837921949526196 MonoBehaviour: m_ObjectHideFlags: 1 @@ -1839,33 +1864,6 @@ AnimatorStateTransition: m_InterruptionSource: 0 m_OrderedInterruption: 1 m_CanTransitionToSelf: 1 ---- !u!1102 &1876505395603539253 -AnimatorState: - serializedVersion: 6 - m_ObjectHideFlags: 1 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: AnticipateMove - m_Speed: 1 - m_CycleOffset: 0 - m_Transitions: - - {fileID: -4504660523056349306} - m_StateMachineBehaviours: [] - m_Position: {x: 50, y: 50, z: 0} - m_IKOnFeet: 0 - m_WriteDefaultValues: 1 - m_Mirror: 0 - m_SpeedParameterActive: 0 - m_MirrorParameterActive: 0 - m_CycleOffsetParameterActive: 0 - m_TimeParameterActive: 0 - m_Motion: {fileID: -4428684883894617094, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3} - m_Tag: - m_SpeedParameter: - m_MirrorParameter: - m_CycleOffsetParameter: - m_TimeParameter: --- !u!1101 &1916661995635438397 AnimatorStateTransition: m_ObjectHideFlags: 1 @@ -1918,31 +1916,6 @@ AnimatorState: m_MirrorParameter: m_CycleOffsetParameter: m_TimeParameter: ---- !u!1101 &2324578261836027962 -AnimatorStateTransition: - m_ObjectHideFlags: 1 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: - m_Conditions: - - m_ConditionMode: 1 - m_ConditionEvent: AnticipateMove - m_EventTreshold: 0 - m_DstStateMachine: {fileID: 0} - m_DstState: {fileID: 1876505395603539253} - m_Solo: 0 - m_Mute: 0 - m_IsExit: 0 - serializedVersion: 3 - m_TransitionDuration: 0 - m_TransitionOffset: 0 - m_ExitTime: 1.2550513e-10 - m_HasExitTime: 0 - m_HasFixedDuration: 1 - m_InterruptionSource: 0 - m_OrderedInterruption: 1 - m_CanTransitionToSelf: 1 --- !u!1101 &2356557320833519340 AnimatorStateTransition: m_ObjectHideFlags: 1 @@ -2636,6 +2609,33 @@ AnimatorState: m_MirrorParameter: m_CycleOffsetParameter: m_TimeParameter: +--- !u!1102 &7052821593652808675 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: AnticipateMove + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: + - {fileID: -97121490881636740} + m_StateMachineBehaviours: [] + m_Position: {x: 50, y: 50, z: 0} + m_IKOnFeet: 0 + m_WriteDefaultValues: 1 + m_Mirror: 0 + m_SpeedParameterActive: 0 + m_MirrorParameterActive: 0 + m_CycleOffsetParameterActive: 0 + m_TimeParameterActive: 0 + m_Motion: {fileID: -3419257869308726280, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: --- !u!1102 &7103618770137260043 AnimatorState: serializedVersion: 6 diff --git a/Assets/BossRoom/Models/CharacterSetController_Tank.overrideController b/Assets/BossRoom/Models/CharacterSetController_Tank.overrideController index 4a8195ae1..30d8e82a4 100644 --- a/Assets/BossRoom/Models/CharacterSetController_Tank.overrideController +++ b/Assets/BossRoom/Models/CharacterSetController_Tank.overrideController @@ -21,3 +21,5 @@ AnimatorOverrideController: m_OverrideClip: {fileID: -6239216113759591374, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3} - m_OriginalClip: {fileID: -5612658629409835226, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3} m_OverrideClip: {fileID: -5612658629409835226, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3} + - m_OriginalClip: {fileID: -4428684883894617094, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3} + m_OverrideClip: {fileID: -3419257869308726280, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3} diff --git a/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs b/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs index a139caf77..c42975641 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs @@ -129,6 +129,7 @@ private void OnClientMoveRequest(Vector3 targetPosition) { if (NetState.NetworkLifeState.Value == LifeState.Alive && !m_Movement.IsPerformingForcedMovement()) { + //NetState. ClearActions(false); m_Movement.SetMovementTarget(targetPosition); } From ad2d31d7fcf87f33fae18cfc99b46d82d3aaffed Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Tue, 16 Mar 2021 14:46:55 -0400 Subject: [PATCH 09/14] more iteration on aticipative actions --- .../GameData/Action/Imp/ImpBaseAttack.asset | 4 +- .../CharacterSetController.controller | 80 ++++++++++++++++++- Assets/BossRoom/Models/CharacterSet.fbx.meta | 9 ++- .../Scripts/Client/Game/Action/ActionFX.cs | 20 ++++- .../Client/Game/Action/ActionVisualization.cs | 8 +- .../Action/FXProjectileTargetedActionFX.cs | 18 ++++- .../Client/Game/Action/TargetActionFX.cs | 4 +- .../Server/Game/Character/ServerCharacter.cs | 2 +- 8 files changed, 128 insertions(+), 17 deletions(-) diff --git a/Assets/BossRoom/GameData/Action/Imp/ImpBaseAttack.asset b/Assets/BossRoom/GameData/Action/Imp/ImpBaseAttack.asset index b097bdd16..adafbe9dd 100644 --- a/Assets/BossRoom/GameData/Action/Imp/ImpBaseAttack.asset +++ b/Assets/BossRoom/GameData/Action/Imp/ImpBaseAttack.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:47b021843aaa2ca179150668d6c9a1de35b6ef65ceef662ed602260fa7fe967c -size 731 +oid sha256:906480816a53904993391f324b0d2c725d76554819f1401ba092b91de7875d00 +size 864 diff --git a/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller b/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller index f0aad7ba3..86477ba4f 100644 --- a/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller +++ b/Assets/BossRoom/Models/Animation Controlers/CharacterSetController.controller @@ -754,6 +754,33 @@ AnimatorStateTransition: m_InterruptionSource: 0 m_OrderedInterruption: 1 m_CanTransitionToSelf: 1 +--- !u!1102 &-5093654682345616202 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: AnticipateMove + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: + - {fileID: 3599037512052606113} + m_StateMachineBehaviours: [] + m_Position: {x: 50, y: 50, z: 0} + m_IKOnFeet: 0 + m_WriteDefaultValues: 1 + m_Mirror: 0 + m_SpeedParameterActive: 0 + m_MirrorParameterActive: 0 + m_CycleOffsetParameterActive: 0 + m_TimeParameterActive: 0 + m_Motion: {fileID: -3419257869308726280, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: --- !u!1102 &-4482486829903005221 AnimatorState: serializedVersion: 6 @@ -954,7 +981,7 @@ AnimatorState: - {fileID: -1751189744513987592} - {fileID: -3322349416516825559} - {fileID: 5808351605165405389} - - {fileID: 426919566368059880} + - {fileID: 5286344766070818967} m_StateMachineBehaviours: [] m_Position: {x: 50, y: 50, z: 0} m_IKOnFeet: 0 @@ -1403,8 +1430,8 @@ AnimatorStateMachine: m_State: {fileID: 7103618770137260043} m_Position: {x: -350, y: 330, z: 0} - serializedVersion: 1 - m_State: {fileID: 7052821593652808675} - m_Position: {x: 370, y: 290, z: 0} + m_State: {fileID: -5093654682345616202} + m_Position: {x: 379.43, y: 329.91626, z: 0} m_ChildStateMachines: [] m_AnyStateTransitions: - {fileID: 6300214233644051234} @@ -2108,6 +2135,28 @@ AnimatorStateMachine: m_ExitPosition: {x: 800, y: 120, z: 0} m_ParentStateMachinePosition: {x: 800, y: 20, z: 0} m_DefaultState: {fileID: -9059899351118470251} +--- !u!1101 &3599037512052606113 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: [] + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: -3516404760485336223} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 0 + serializedVersion: 3 + m_TransitionDuration: 0.35027 + m_TransitionOffset: 0.118458696 + m_ExitTime: 0.40587464 + m_HasExitTime: 1 + m_HasFixedDuration: 1 + m_InterruptionSource: 2 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 --- !u!1101 &4047612268588016952 AnimatorStateTransition: m_ObjectHideFlags: 1 @@ -2336,6 +2385,31 @@ AnimatorStateTransition: m_InterruptionSource: 0 m_OrderedInterruption: 1 m_CanTransitionToSelf: 1 +--- !u!1101 &5286344766070818967 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: + - m_ConditionMode: 1 + m_ConditionEvent: AnticipateMove + m_EventTreshold: 0 + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: -5093654682345616202} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 0 + serializedVersion: 3 + m_TransitionDuration: 0.185271 + m_TransitionOffset: 0.051008537 + m_ExitTime: 0.031880304 + m_HasExitTime: 0 + m_HasFixedDuration: 0 + m_InterruptionSource: 2 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 --- !u!1101 &5537143230144326077 AnimatorStateTransition: m_ObjectHideFlags: 1 diff --git a/Assets/BossRoom/Models/CharacterSet.fbx.meta b/Assets/BossRoom/Models/CharacterSet.fbx.meta index 061ff0177..fd904d991 100644 --- a/Assets/BossRoom/Models/CharacterSet.fbx.meta +++ b/Assets/BossRoom/Models/CharacterSet.fbx.meta @@ -2182,7 +2182,14 @@ ModelImporter: mirror: 0 bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 curves: [] - events: [] + events: + - time: 0.504353 + functionName: OnAnimEvent + data: impact + objectReferenceParameter: {instanceID: 0} + floatParameter: 0 + intParameter: 0 + messageOptions: 0 transformMask: [] maskType: 3 maskSource: {instanceID: 0} diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs index ba6bf6e3e..7718ac5dc 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs @@ -85,15 +85,29 @@ public static ActionFX MakeActionFX(ref ActionRequestData data, ClientCharacterV /// /// Should this ActionFX be created anticipatively on the owning client? /// + /// The ActionVisualization that would be playing this ActionFX. /// The request being sent to the server /// If true ActionVisualization should pre-emptively create the ActionFX on the owning client, before hearing back from the server. - public static bool ShouldAnticipate(ref ActionRequestData data) + public static bool ShouldAnticipate(ActionVisualization parent, ref ActionRequestData data) { - var actionLogic = GameDataSource.Instance.ActionDataByType[data.ActionTypeEnum].Logic; + var actionDescription = GameDataSource.Instance.ActionDataByType[data.ActionTypeEnum]; + + //for actions with ShouldClose set, we check our range locally. If we are out of range, we shouldn't anticipate, as we will + //need to execute a ChaseAction (synthesized on the server) prior to actually playing the skill. + bool isTargetEligible = true; + if( data.ShouldClose == true ) + { + ulong targetId = (data.TargetIds != null && data.TargetIds.Length > 0) ? data.TargetIds[0] : 0; + if( MLAPI.Spawning.NetworkSpawnManager.SpawnedObjects.TryGetValue(targetId, out MLAPI.NetworkObject networkObject ) ) + { + float rangeSquared = actionDescription.Range * actionDescription.Range; + isTargetEligible = (networkObject.transform.position - parent.Parent.transform.position).sqrMagnitude < rangeSquared; + } + } //at present all Actionts anticipate except for the Target action, which runs a single instance on the client and is //responsible for action anticipation on its own. - return actionLogic != ActionLogic.Target; + return isTargetEligible && actionDescription.Logic != ActionLogic.Target; } public virtual void OnAnimEvent(string id) { } diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs b/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs index ac7820282..725f72c37 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs @@ -45,9 +45,9 @@ public void Update() } //helper wrapper for a FindIndex call on m_PlayingActions. - private int FindAction(ActionType action ) + private int FindAction(ActionType action, bool anticipatedOnly ) { - return m_PlayingActions.FindIndex(a => a.Description.ActionTypeEnum == action); + return m_PlayingActions.FindIndex(a => a.Description.ActionTypeEnum == action && (!anticipatedOnly || a.Anticipated)); } public void OnAnimEvent(string id) @@ -88,7 +88,7 @@ public void OnStoppedChargingUp() public void AnticipateAction(ref ActionRequestData data) { - if (!Parent.IsAnimating && ActionFX.ShouldAnticipate(ref data)) + if (!Parent.IsAnimating && ActionFX.ShouldAnticipate(this, ref data)) { var actionFX = ActionFX.MakeActionFX(ref data, Parent); actionFX.TimeStarted = Time.time; @@ -99,7 +99,7 @@ public void AnticipateAction(ref ActionRequestData data) public void PlayAction(ref ActionRequestData data) { - var anticipatedActionIndex = FindAction(data.ActionTypeEnum); + var anticipatedActionIndex = FindAction(data.ActionTypeEnum, true); var actionFX = anticipatedActionIndex>=0 ? m_PlayingActions[anticipatedActionIndex] : ActionFX.MakeActionFX(ref data, Parent); actionFX.TimeStarted = Time.time; diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs index 6afe405df..5867e151c 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs @@ -25,6 +25,7 @@ public FXProjectileTargetedActionFX(ref ActionRequestData data, ClientCharacterV public override bool Start() { + bool wasAnticipated = Anticipated; base.Start(); m_Target = GetTarget(); if (HasTarget() && m_Target == null) @@ -45,10 +46,19 @@ public override bool Start() m_Projectile = SpawnAndInitializeProjectile(); // animate shooting the projectile - m_Parent.OurAnimator.SetTrigger(Description.Anim); + if( !wasAnticipated ) + { + PlayFireAnim(); + } + return true; } + private void PlayFireAnim() + { + m_Parent.OurAnimator.SetTrigger(Description.Anim); + } + public override bool Update() { // we keep going until the projectile's duration ends @@ -129,5 +139,11 @@ private FXProjectile SpawnAndInitializeProjectile() projectile.Initialize(m_Parent.transform.position, m_Target?.transform, m_Data.Position, Description.ExecTimeSeconds, m_ProjectileDuration); return projectile; } + + public override void AnticipateAction() + { + base.AnticipateAction(); + PlayFireAnim(); + } } } diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs index 9ebb9db13..d92e489ac 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/TargetActionFX.cs @@ -49,9 +49,9 @@ private void OnActionInput(ActionRequestData data ) public override bool Update() { - if( m_CurrentTarget != m_ParentState.TargetId.Value ) + if( m_CurrentTarget != m_NewTarget ) { - m_CurrentTarget = m_ParentState.TargetId.Value; + m_CurrentTarget = m_NewTarget; if (NetworkSpawnManager.SpawnedObjects.TryGetValue(m_CurrentTarget, out NetworkObject targetObject ) ) { diff --git a/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs b/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs index c42975641..83f9b80ff 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs @@ -129,8 +129,8 @@ private void OnClientMoveRequest(Vector3 targetPosition) { if (NetState.NetworkLifeState.Value == LifeState.Alive && !m_Movement.IsPerformingForcedMovement()) { - //NetState. ClearActions(false); + m_ActionPlayer.CancelRunningActionsByLogic(ActionLogic.Target, true); //clear target on move. m_Movement.SetMovementTarget(targetPosition); } } From 39adfaaf4e4c0b39456bd9b9fea72928bc2ad2ec Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Tue, 16 Mar 2021 16:51:17 -0400 Subject: [PATCH 10/14] heavy comment about anticipative actions, and cleaned up issue with hold-to-move --- .../Scripts/Client/Game/Action/ActionFX.cs | 4 ++- .../Client/Game/Action/ActionVisualization.cs | 28 +++++++++++++------ .../Character/ClientCharacterVisualization.cs | 8 ++++-- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs index 7718ac5dc..37163b341 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs @@ -12,7 +12,7 @@ public abstract class ActionFX : ActionBase /// The default hit react animation; several different ActionFXs make use of this. /// public const string k_DefaultHitReact = "HitReact1"; - + /// /// True if this actionFX began running immediately, prior to getting a confirmation from the server. /// @@ -33,6 +33,7 @@ public ActionFX(ref ActionRequestData data, ClientCharacterVisualization parent) public virtual bool Start() { Anticipated = false; //once you start for real you are no longer an anticipated action. + TimeStarted = UnityEngine.Time.time; return true; } @@ -121,6 +122,7 @@ public virtual void OnStoppedChargingUp() { } public virtual void AnticipateAction() { Anticipated = true; + TimeStarted = UnityEngine.Time.time; } } diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs b/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs index 725f72c37..dabf0fcbc 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs @@ -70,6 +70,14 @@ public void OnStoppedChargingUp() /// Called on the client that owns the Character when the player triggers an action. This allows actions to immediately start playing feedback. /// /// + /// + /// What is Action Anticipation and what problem does it solve? In short, it lets Actions run logic the moment the input event that triggers them + /// is detected on the local client. The purpose of this is to help mask latency. Because this demo is server authoritative, the default behavior is + /// to only see feedback for your input after a server-client roundtrip. Somewhere over 200ms of round-trip latency, this starts to feel oppressively sluggish. + /// To combat this, you can play visual effects immediately. For example, MeleeActionFX plays both its weapon swing and applies a hit react to the target, + /// without waiting to hear from the server. This can lead to discrepancies when the server doesn't think the target was hit, but on the net, will feel + /// more responsive. + /// /// An important concept of Action Anticipation is that it is opportunistic--it doesn't make any strong guarantees. You don't get an anticipated /// action animation if you are already animating in some way, as one example. Another complexity is that you don't know if the server will actually /// let you play all the actions that you've requested--some may get thrown away, e.g. because you have too many actions in your queue. What this means @@ -78,20 +86,25 @@ public void OnStoppedChargingUp() /// Characters belonging to the server and other characters anyway). It also means we need to handle the case where we created an Anticipated Action, but /// never got a confirmation--actions like that need to eventually get discarded. /// - /// Current limitations: - /// * the only anticipation performed is to play an animation. - /// * Individual Actions might need to implement their own sophisticated Anticipation logic. For example, LaunchProjectile could actually create the projectile - /// and start it moving along its expected path, and then somehow link up its purely visual projectile with the real networked projectile that the server - /// eventually creates. + /// Another important aspect of Anticipated Actions is that they are an "opt-in" system. You must call base.Start in your Start implementation, but other than + /// that, if you don't have a good way to implement an Anticipation for your action, you don't have to do anything. In this case, that action will play + /// "normally" (with visual feedback starting when the server's action broadcast reaches the client). Every action type will have its own particular set of + /// problems to solve to sell the anticipation effect. For example, in this demo, the mage base attack (FXProjectileTargetedActionFX) just plays the attack animation + /// anticipatively, but it could be revised to create and drive the mage bolt effect as well--leaving only damage to arrive in true server time. + /// + /// How to implement your own Anticipation logic: + /// 1. Isolate the visual feedback you want play anticipatively in a private helper method on your ActionFX, like "PlayAttackAnim". + /// 2. Override ActionFX.AnticipateAction. Be sure to call base.AnticipateAction, as well as play your visual logic (like PlayAttackAnim). + /// 3. In your Start method, be sure to call base.Start (note that this will reset the "Anticipated" field to false). + /// 4. In Start, check if the action was Anticipated. If NOT, then play call your PlayAttackAnim method. + /// /// /// The Action that is being requested. - public void AnticipateAction(ref ActionRequestData data) { if (!Parent.IsAnimating && ActionFX.ShouldAnticipate(this, ref data)) { var actionFX = ActionFX.MakeActionFX(ref data, Parent); - actionFX.TimeStarted = Time.time; actionFX.AnticipateAction(); m_PlayingActions.Add(actionFX); } @@ -102,7 +115,6 @@ public void PlayAction(ref ActionRequestData data) var anticipatedActionIndex = FindAction(data.ActionTypeEnum, true); var actionFX = anticipatedActionIndex>=0 ? m_PlayingActions[anticipatedActionIndex] : ActionFX.MakeActionFX(ref data, Parent); - actionFX.TimeStarted = Time.time; if (actionFX.Start()) { m_PlayingActions.Add(actionFX); diff --git a/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs b/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs index be5f73fbe..ea93486c9 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Character/ClientCharacterVisualization.cs @@ -300,9 +300,11 @@ public bool IsAnimating { get { - //layer 0 is our movement layer, and has a special base state. - bool animating = !OurAnimator.GetCurrentAnimatorStateInfo(0).IsName("WalkRun") || OurAnimator.GetFloat("Speed") > 0.0; - if (animating) { return false; } + //layer 0 is our movement layer, and has a special base state. We detect if we are animating solely based on the Speed parameter. + if (OurAnimator.GetFloat("Speed") > 0.0 ) + { + return true; + } for (int i = 1; i < OurAnimator.layerCount; i++) { From 26802877893c6519b87833a29974732852b76aca Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Tue, 16 Mar 2021 17:20:17 -0400 Subject: [PATCH 11/14] removing some debug logs --- Assets/BossRoom/Scripts/Client/Game/Utils/SelfDisable.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Assets/BossRoom/Scripts/Client/Game/Utils/SelfDisable.cs b/Assets/BossRoom/Scripts/Client/Game/Utils/SelfDisable.cs index affc8ee38..8dbd289dd 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Utils/SelfDisable.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Utils/SelfDisable.cs @@ -14,7 +14,6 @@ void Update() { if (Time.time >= m_DisableTimestamp) { - Debug.Log($"Click Feedback disabling at {Time.time}"); gameObject.SetActive(false); } } @@ -22,6 +21,5 @@ void Update() void OnEnable() { m_DisableTimestamp = Time.time + m_DisabledDelay; - Debug.Log($"Enabling Click Feedback at: {Time.time}, will disable at {m_DisableTimestamp}"); } } From 99a1a6d007f65481439e83239ea3dbbbcc640b10 Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Tue, 16 Mar 2021 17:53:10 -0400 Subject: [PATCH 12/14] updating back to 2020.3 --- ProjectSettings/ProjectVersion.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index 0560e11dd..4db0bd06e 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2020.2.0f1 -m_EditorVersionWithRevision: 2020.2.0f1 (3721df5a8b28) +m_EditorVersion: 2020.3.0f1 +m_EditorVersionWithRevision: 2020.3.0f1 (c7b5465681fb) From 323cd8d9242a9941235055ab33c595d31916f194 Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Wed, 17 Mar 2021 15:33:19 -0400 Subject: [PATCH 13/14] updating click feedback --- Assets/BossRoom/Scripts/Client/ClickFeedback.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Assets/BossRoom/Scripts/Client/ClickFeedback.cs b/Assets/BossRoom/Scripts/Client/ClickFeedback.cs index 6d4d5a580..3cb429a6b 100644 --- a/Assets/BossRoom/Scripts/Client/ClickFeedback.cs +++ b/Assets/BossRoom/Scripts/Client/ClickFeedback.cs @@ -27,12 +27,12 @@ void Start() } m_ClientSender = GetComponent(); - m_ClientSender.ClientMoveEvent += onClick; + m_ClientSender.ClientMoveEvent += onClientMove; m_FeedbackObj = Instantiate(m_FeedbackPrefab); m_FeedbackObj.SetActive(false); } - void onClick(Vector3 position) + void onClientMove(Vector3 position) { position.y += HOVER_HEIGHT; @@ -44,7 +44,7 @@ private void OnDestroy() { if (m_ClientSender) { - m_ClientSender.ClientMoveEvent -= onClick; + m_ClientSender.ClientMoveEvent -= onClientMove; } } } From 6ae9f80efdd98f3b51cd92469226effcedaf33d2 Mon Sep 17 00:00:00 2001 From: David Woodruff Date: Wed, 17 Mar 2021 15:33:46 -0400 Subject: [PATCH 14/14] renaming timestarted and timerunning --- Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs | 4 ++-- .../Scripts/Client/Game/Action/ActionVisualization.cs | 4 ++-- .../Client/Game/Action/FXProjectileTargetedActionFX.cs | 2 +- .../Scripts/Client/Game/Action/StealthModeActionFX.cs | 2 +- .../BossRoom/Scripts/Client/Game/Action/TrampleActionFX.cs | 2 +- Assets/BossRoom/Scripts/Server/Game/Action/AOEAction.cs | 2 +- Assets/BossRoom/Scripts/Server/Game/Action/Action.cs | 4 ++-- Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs | 6 +++--- .../Server/Game/Action/ChargedLaunchProjectileAction.cs | 4 ++-- .../Scripts/Server/Game/Action/ChargedShieldAction.cs | 6 +++--- .../Server/Game/Action/FXProjectileTargetedAction.cs | 2 +- .../Scripts/Server/Game/Action/LaunchProjectileAction.cs | 2 +- Assets/BossRoom/Scripts/Server/Game/Action/MeleeAction.cs | 2 +- Assets/BossRoom/Scripts/Server/Game/Action/ReviveAction.cs | 2 +- .../Scripts/Server/Game/Action/StealthModeAction.cs | 4 ++-- Assets/BossRoom/Scripts/Server/Game/Action/TrampleAction.cs | 2 +- Assets/BossRoom/Scripts/Shared/Game/Action/ActionBase.cs | 4 ++-- 17 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs index 37163b341..b9db06571 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/ActionFX.cs @@ -33,7 +33,7 @@ public ActionFX(ref ActionRequestData data, ClientCharacterVisualization parent) public virtual bool Start() { Anticipated = false; //once you start for real you are no longer an anticipated action. - TimeStarted = UnityEngine.Time.time; + TimeStartedSeconds = UnityEngine.Time.time; return true; } @@ -122,7 +122,7 @@ public virtual void OnStoppedChargingUp() { } public virtual void AnticipateAction() { Anticipated = true; - TimeStarted = UnityEngine.Time.time; + TimeStartedSeconds = UnityEngine.Time.time; } } diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs b/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs index dabf0fcbc..258551e77 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/ActionVisualization.cs @@ -32,8 +32,8 @@ public void Update() var action = m_PlayingActions[i]; bool keepGoing = action.Update(); bool expirable = action.Description.DurationSeconds > 0f; //non-positive value is a sentinel indicating the duration is indefinite. - bool timeExpired = expirable && action.TimeRunning >= action.Description.DurationSeconds; - bool timedOut = action.Anticipated && action.TimeRunning >= k_AnticipationTimeoutSeconds; + bool timeExpired = expirable && action.TimeRunningSeconds >= action.Description.DurationSeconds; + bool timedOut = action.Anticipated && action.TimeRunningSeconds >= k_AnticipationTimeoutSeconds; if (!keepGoing || timeExpired || timedOut) { if (timedOut) { action.Cancel(); } //an anticipated action that timed out shouldn't get its End called. It is canceled instead. diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs index 5867e151c..df4817c78 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/FXProjectileTargetedActionFX.cs @@ -62,7 +62,7 @@ private void PlayFireAnim() public override bool Update() { // we keep going until the projectile's duration ends - return (Time.time - TimeStarted) <= m_ProjectileDuration + Description.ExecTimeSeconds; + return (Time.time - TimeStartedSeconds) <= m_ProjectileDuration + Description.ExecTimeSeconds; } public override void OnAnimEvent(string id) diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/StealthModeActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/StealthModeActionFX.cs index 917eae680..d2412107e 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/StealthModeActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/StealthModeActionFX.cs @@ -34,7 +34,7 @@ public override bool Start() public override bool Update() { - if (TimeRunning >= Description.ExecTimeSeconds && m_SpawnedGraphics == null && m_Parent.IsOwner) + if (TimeRunningSeconds >= Description.ExecTimeSeconds && m_SpawnedGraphics == null && m_Parent.IsOwner) { m_SpawnedGraphics = new List(); foreach (var prefab in Description.Spawns) diff --git a/Assets/BossRoom/Scripts/Client/Game/Action/TrampleActionFX.cs b/Assets/BossRoom/Scripts/Client/Game/Action/TrampleActionFX.cs index bfd36086c..05c3cb1c6 100644 --- a/Assets/BossRoom/Scripts/Client/Game/Action/TrampleActionFX.cs +++ b/Assets/BossRoom/Scripts/Client/Game/Action/TrampleActionFX.cs @@ -44,7 +44,7 @@ public override bool Start() public override bool Update() { - float age = Time.time - TimeStarted; + float age = Time.time - TimeStartedSeconds; if (age > k_GraphicsSpawnDelay && m_SpawnedGraphics == null) { m_SpawnedGraphics = new List(); diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/AOEAction.cs b/Assets/BossRoom/Scripts/Server/Game/Action/AOEAction.cs index 8fe60a619..ef09ce330 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/AOEAction.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/AOEAction.cs @@ -41,7 +41,7 @@ public override bool Start() public override bool Update() { - if (TimeRunning >= Description.ExecTimeSeconds && !m_DidAoE) + if (TimeRunningSeconds >= Description.ExecTimeSeconds && !m_DidAoE) { // actually perform the AoE attack m_DidAoE = true; diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/Action.cs b/Assets/BossRoom/Scripts/Server/Game/Action/Action.cs index 5b12ae7ca..82a0f98b2 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/Action.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/Action.cs @@ -55,8 +55,8 @@ public Action(ServerCharacter parent, ref ActionRequestData data) : base(ref dat /// true to become a non-blocking Action, false to remain a blocking Action public virtual bool ShouldBecomeNonBlocking() { - return Description.BlockingMode == BlockingMode.OnlyDuringExecTime ? TimeRunning >= Description.ExecTimeSeconds : - Description.BlockingMode == BlockingMode.ExecTimeWithCooldown ? TimeRunning >= (Description.ExecTimeSeconds + Description.CooldownSeconds) : + return Description.BlockingMode == BlockingMode.OnlyDuringExecTime ? TimeRunningSeconds >= Description.ExecTimeSeconds : + Description.BlockingMode == BlockingMode.ExecTimeWithCooldown ? TimeRunningSeconds >= (Description.ExecTimeSeconds + Description.CooldownSeconds) : false; } diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs b/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs index ffcb519a6..be78f7fa7 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/ActionPlayer.cs @@ -112,7 +112,7 @@ private void StartAction() int index = SynthesizeTargetIfNecessary(0); SynthesizeChaseIfNecessary(index); - m_Queue[0].TimeStarted = Time.time; + m_Queue[0].TimeStartedSeconds = Time.time; bool play = m_Queue[0].Start(); if (!play) { @@ -260,7 +260,7 @@ private bool UpdateAction(Action action) { bool keepGoing = action.Update(); bool expirable = action.Description.DurationSeconds > 0f; //non-positive value is a sentinel indicating the duration is indefinite. - var timeElapsed = Time.time - action.TimeStarted; + var timeElapsed = Time.time - action.TimeStartedSeconds; bool timeExpired = expirable && timeElapsed >= (action.Description.DurationSeconds + action.Description.CooldownSeconds); return keepGoing && !timeExpired; @@ -286,7 +286,7 @@ private float GetQueueTimeDepth() totalTime += actionTime; } - return totalTime - m_Queue[0].TimeRunning; + return totalTime - m_Queue[0].TimeRunningSeconds; } public void OnCollisionEnter(Collision collision) diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/ChargedLaunchProjectileAction.cs b/Assets/BossRoom/Scripts/Server/Game/Action/ChargedLaunchProjectileAction.cs index da78d57d1..91bdccfef 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/ChargedLaunchProjectileAction.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/ChargedLaunchProjectileAction.cs @@ -68,7 +68,7 @@ public override bool Update() if (m_StoppedChargingUpTime == 0) { // we haven't explicitly stopped charging up... but if we've reached max charge, that implicitly stops us - if (TimeRunning >= Description.ExecTimeSeconds) + if (TimeRunningSeconds >= Description.ExecTimeSeconds) { StopChargingUp(); } @@ -129,7 +129,7 @@ protected override ActionDescription.ProjectileInfo GetProjectileInfo() if (Description.Projectiles.Length == 0) // uh oh, this is bad data throw new System.Exception($"Action {Description.ActionTypeEnum} has no Projectiles!"); - float timeSpentChargingUp = m_StoppedChargingUpTime - TimeStarted; + float timeSpentChargingUp = m_StoppedChargingUpTime - TimeStartedSeconds; float pctChargedUp = Mathf.Clamp01(timeSpentChargingUp / Description.ExecTimeSeconds); // Finally, choose which prefab to use based on how charged-up we got. diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/ChargedShieldAction.cs b/Assets/BossRoom/Scripts/Server/Game/Action/ChargedShieldAction.cs index 74a99c2d6..c6846fe04 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/ChargedShieldAction.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/ChargedShieldAction.cs @@ -59,7 +59,7 @@ public override bool Update() if (m_StoppedChargingUpTime == 0) { // we haven't explicitly stopped charging up... but if we've reached max charge, that implicitly stops us - if (TimeRunning >= Description.ExecTimeSeconds) + if (TimeRunningSeconds >= Description.ExecTimeSeconds) { StopChargingUp(); } @@ -78,7 +78,7 @@ public override void BuffValue(BuffableValue buffType, ref float buffedValue) { if (buffType == BuffableValue.PercentDamageReceived) { - float timeSpentChargingUp = m_StoppedChargingUpTime - TimeStarted; + float timeSpentChargingUp = m_StoppedChargingUpTime - TimeStartedSeconds; float pctChargedUp = Mathf.Clamp01(timeSpentChargingUp / Description.ExecTimeSeconds); // the amount of damage reduction starts at 50% (for not-charged-up), then slowly increases to 100% depending on how charged-up we got @@ -93,7 +93,7 @@ public override void BuffValue(BuffableValue buffType, ref float buffedValue) else if (buffType == BuffableValue.ChanceToStunTramplers) { // if we are at "full charge", we stun enemies that try to trample us! - float timeSpentChargingUp = m_StoppedChargingUpTime - TimeStarted; + float timeSpentChargingUp = m_StoppedChargingUpTime - TimeStartedSeconds; if (timeSpentChargingUp / Description.ExecTimeSeconds >= 1 && buffedValue < 1) { buffedValue = 1; diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/FXProjectileTargetedAction.cs b/Assets/BossRoom/Scripts/Server/Game/Action/FXProjectileTargetedAction.cs index 31379f0f6..b230c2e31 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/FXProjectileTargetedAction.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/FXProjectileTargetedAction.cs @@ -42,7 +42,7 @@ public override bool Start() public override bool Update() { - if (!m_ImpactedTarget && m_TimeUntilImpact <= (Time.time - TimeStarted)) + if (!m_ImpactedTarget && m_TimeUntilImpact <= (Time.time - TimeStartedSeconds)) { m_ImpactedTarget = true; if (m_Target != null ) diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/LaunchProjectileAction.cs b/Assets/BossRoom/Scripts/Server/Game/Action/LaunchProjectileAction.cs index 2cf073742..e4c4831d5 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/LaunchProjectileAction.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/LaunchProjectileAction.cs @@ -23,7 +23,7 @@ public override bool Start() public override bool Update() { - if (TimeRunning >= Description.ExecTimeSeconds && !m_Launched) + if (TimeRunningSeconds >= Description.ExecTimeSeconds && !m_Launched) { LaunchProjectile(); } diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/MeleeAction.cs b/Assets/BossRoom/Scripts/Server/Game/Action/MeleeAction.cs index a1d47117e..2f8d6ccde 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/MeleeAction.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/MeleeAction.cs @@ -51,7 +51,7 @@ public override bool Start() public override bool Update() { - if (!m_ExecutionFired && (Time.time - TimeStarted) >= Description.ExecTimeSeconds) + if (!m_ExecutionFired && (Time.time - TimeStartedSeconds) >= Description.ExecTimeSeconds) { m_ExecutionFired = true; var foe = DetectFoe(m_ProvisionalTarget); diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/ReviveAction.cs b/Assets/BossRoom/Scripts/Server/Game/Action/ReviveAction.cs index 731dd2abe..1fd921862 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/ReviveAction.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/ReviveAction.cs @@ -29,7 +29,7 @@ public override bool Start() public override bool Update() { - if (!m_ExecFired && Time.time - TimeStarted >= Description.ExecTimeSeconds) + if (!m_ExecFired && Time.time - TimeStartedSeconds >= Description.ExecTimeSeconds) { m_ExecFired = true; diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/StealthModeAction.cs b/Assets/BossRoom/Scripts/Server/Game/Action/StealthModeAction.cs index 6cead3f08..24ce722e6 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/StealthModeAction.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/StealthModeAction.cs @@ -31,12 +31,12 @@ public override bool Start() public override bool ShouldBecomeNonBlocking() { - return TimeRunning >= Description.ExecTimeSeconds; + return TimeRunningSeconds >= Description.ExecTimeSeconds; } public override bool Update() { - if (TimeRunning >= Description.ExecTimeSeconds && !m_IsStealthStarted && !m_IsStealthEnded) + if (TimeRunningSeconds >= Description.ExecTimeSeconds && !m_IsStealthStarted && !m_IsStealthEnded) { // start actual stealth-mode... NOW! m_IsStealthStarted = true; diff --git a/Assets/BossRoom/Scripts/Server/Game/Action/TrampleAction.cs b/Assets/BossRoom/Scripts/Server/Game/Action/TrampleAction.cs index fedd5f28d..8347fe4f2 100644 --- a/Assets/BossRoom/Scripts/Server/Game/Action/TrampleAction.cs +++ b/Assets/BossRoom/Scripts/Server/Game/Action/TrampleAction.cs @@ -73,7 +73,7 @@ public override bool Start() private ActionStage GetCurrentStage() { - float timeSoFar = Time.time - TimeStarted; + float timeSoFar = TimeRunningSeconds; if (timeSoFar < Description.ExecTimeSeconds) { return ActionStage.Windup; diff --git a/Assets/BossRoom/Scripts/Shared/Game/Action/ActionBase.cs b/Assets/BossRoom/Scripts/Shared/Game/Action/ActionBase.cs index 610e7204b..8d35afdb1 100644 --- a/Assets/BossRoom/Scripts/Shared/Game/Action/ActionBase.cs +++ b/Assets/BossRoom/Scripts/Shared/Game/Action/ActionBase.cs @@ -12,12 +12,12 @@ public abstract class ActionBase /// /// Time when this Action was started (from Time.time) in seconds. Set by the ActionPlayer or ActionVisualization. /// - public float TimeStarted { get; set; } + public float TimeStartedSeconds { get; set; } /// /// How long the Action has been running (since its Start was called)--in seconds, measured via Time.time. /// - public float TimeRunning { get { return (Time.time - TimeStarted); } } + public float TimeRunningSeconds { get { return (Time.time - TimeStartedSeconds); } } /// /// RequestData we were instantiated with. Value should be treated as readonly.