using DG.Tweening; using DG.Tweening.Core; using DG.Tweening.Plugins.Options; using Spine.Unity; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using AnimationState = Spine.AnimationState; public class IVPet : MonoBehaviour { [SerializeField] private Transform trfTarget; [SerializeField] private float fMoveSpeed = 0.1f; [SerializeField] private Vector3 v3Offset = Vector3.zero; private Vector3 v3OffsetRev = Vector3.zero; private Vector3 v3posto; private Vector3 v3RandomPos; private Vector3 v3dir; private SkeletonAnimation skAnim; private TweenerCore twcSummon = null; private TweenerCore twcSummonRev = null; private TweenerCore twcUnsummon = null; private TweenerCore twcUnsummonRev = null; private TweenerCore twcMove = null; private TweenerCore twcMoveX = null; private int Key = -1; private bool bFrontRight = true; private bool bInitNeed = true; [SerializeField] private bool bSet = true; private bool bMove = false; private bool bMoveFlag = false; private bool bSummoning = false; private AnimationState anState; private AsyncOperationHandle handlePet; public void Init() { Transform trfwrapper = transform.GetChild(0); Transform trfpet = trfwrapper.GetChild(0); skAnim = trfpet.GetComponent(); twcSummon = transform.DOScale(Global.V3_1, 0.2f).ChangeStartValue(Global.V3_001).SetEase(Ease.OutQuad).OnComplete(SummonEnd).SetAutoKill(false).Pause(); twcSummonRev = transform.DOScale(Global.V3_1XRev, 0.2f).ChangeStartValue(Global.V3_001XRev).SetEase(Ease.OutQuad).OnComplete(SummonEnd).SetAutoKill(false).Pause(); twcUnsummon = transform.DOScale(Global.V3_001, 0.2f).ChangeStartValue(Global.V3_1).SetEase(Ease.InQuad).OnComplete(UnsummonEnd).SetAutoKill(false).Pause(); twcUnsummonRev = transform.DOScale(Global.V3_001XRev, 0.2f).ChangeStartValue(Global.V3_1XRev).SetEase(Ease.InQuad).OnComplete(UnsummonEnd).SetAutoKill(false).Pause(); transform.position = trfTarget.position + Random.insideUnitSphere * Random.Range(5, 7); bInitNeed = false; } #region Summon // 펫 소환 완료. private void SummonEnd() { twcMove.Play(); twcMoveX.Play(); bSummoning = false; } // 펫 소환 해제 완료. private void UnsummonEnd() { gameObject.SetActive(false); } // 펫 소환. public void Summon() { if (Key < 0) return; v3RandomPos = Random.insideUnitCircle * Random.Range(3, 5); transform.position = new Vector3(trfTarget.position.x + v3RandomPos.x, trfTarget.position.y + v3RandomPos.y, (trfTarget.position.y + v3RandomPos.y)*0.1f); if (bFrontRight) twcSummon.Restart(); else twcSummonRev.Restart(); gameObject.SetActive(true); anState = skAnim.AnimationState; if (bSet) { bMove = false; anState.SetAnimation(0, "idle", true); } } // 펫 소환 해제. public void Unsummon() { if (Key < 0) return; bSummoning = true; twcMove.Pause(); twcMoveX.Pause(); if (bFrontRight) twcUnsummon.Restart(); else twcUnsummonRev.Restart(); } // 펫 끄기. public void OffPet() { twcMove.Pause(); twcMoveX.Pause(); gameObject.SetActive(false); } #endregion Summon #region Set public bool IsPetOn() { return Key >= 0; } public void SetPet(int key) { // 변경사항 없음. if (key == Key) return; // 펫 없음. if (key < 0) { if (Key >= 0) { Key = -1; bSet = false; if (skAnim.skeletonDataAsset != null) skAnim.skeletonDataAsset.Clear(); skAnim.ClearState(); gameObject.SetActive(false); } return; } // 펫 있음. Key = key; bSet = false; CoverCamera.Hold(); if (skAnim.skeletonDataAsset != null) skAnim.skeletonDataAsset.Clear(); skAnim.ClearState(); //@ for test switch (key) { case 33: key = 44; break; } Addressables.LoadAssetAsync(FormatString.StringFormat(AddressableMgr.PathPet, key.ToString())).Completed += ALoadPetComp; } #endregion Set #region Position protected void LateUpdate() { if (bInitNeed || bSummoning) return; // = trfTarget.position; // 거리가 5이상 멀어지고, 이동이 불가능한 상태면 다음 위치 할당 후 MoveFlag를 true로 변경 if (BattleMgr.SCalcDistance(trfTarget.position, transform.position) > 4 && !bMoveFlag) { if (bFrontRight) { v3RandomPos = Random.insideUnitCircle * Random.Range(3, 5); bMoveFlag = true; anState.SetAnimation(0, "move", true); } else { v3RandomPos = Random.insideUnitCircle * Random.Range(3, 5); //trfTarget.position + v3OffsetRev; bMoveFlag = true; anState.SetAnimation(0, "move", true); } v3RandomPos.y = Mathf.Clamp(v3RandomPos.y, v3RandomPos.y, 0); } // MoveFlag가 true면 이동 시작 if(bMoveFlag) { if (bSet) { v3posto = new Vector3(trfTarget.position.x + v3RandomPos.x,trfTarget.position.y + v3RandomPos.y, (trfTarget.position.y + v3RandomPos.y) * 0.1f); v3dir = (v3posto - transform.position).normalized; transform.position = transform.position + v3dir * (0.1f * fMoveSpeed); // Vector3.Lerp(transform.position, v3posto, fSmoothSpeed); float fdistance = BattleMgr.SCalcDistance(transform.position, v3posto); ChangeFrontToTarget(); if (fdistance <= 1.3f && bMove) { bMove = false; bMoveFlag = false; anState.SetAnimation(0, "idle", true); } if (fdistance > 1.3f && !bMove) { bMove = true; anState.SetAnimation(0, "move", true); } } } } // 바라보는 방향 및 위치 초기화. public void SetFront(bool bfrontright) { bFrontRight = bfrontright; if (bFrontRight) { transform.localScale = Global.V3_1; transform.position = trfTarget.position + v3Offset; } else { transform.localScale = Global.V3_1XRev; transform.position = trfTarget.position + v3OffsetRev; } } // 바라보는 방향 변경. public void ChangeFront(bool bfrontright) { if (bfrontright == bFrontRight) return; bFrontRight = bfrontright; if (bFrontRight) transform.localScale = Global.V3_1; else transform.localScale = Global.V3_1XRev; } public void ChangeFrontToTarget() { if (transform.position.x - v3posto.x < -0.1f) transform.localScale = Global.V3_1; else if (transform.position.x - v3posto.x > 0.1f) transform.localScale = Global.V3_1XRev; else return; } #endregion Position #region Addressable private void ALoadPetComp(AsyncOperationHandle obj) { skAnim.skeletonDataAsset = obj.Result; skAnim.Initialize(true); anState = skAnim.AnimationState; //AtlasUtilities.ClearCache(); if (handlePet.IsValid()) { Addressables.Release(handlePet); AddressableMgr.SAddUnload(); } handlePet = obj; CoverCamera.Release(); bSet = true; if (BattleMgr.Instance.BattlePause) return; Summon(); } #endregion Addressable }