OldBlueWater/BlueWater/Assets/02.Scripts/Skill/ActiveSkill/ActiveSkill.cs

239 lines
7.2 KiB
C#
Raw Normal View History

2023-10-31 07:37:23 +00:00
using System;
using System.Collections;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Rendering.Universal;
2023-10-31 07:37:23 +00:00
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public enum EIndicatorType
{
NONE,
RADIUS,
AREA,
CONE,
LINE
}
2023-10-31 07:37:23 +00:00
[Serializable]
public class ActiveSkill : MonoBehaviour
2023-10-31 07:37:23 +00:00
{
#region Properties and variables
// So
[Title("DataSo")]
[Required("So를 추가해주세요.")]
[SerializeField] private SkillIndicatorData skillIndicatorDataSo;
[Required("So를 추가해주세요.")]
[SerializeField] private ActiveSkillData activeSkillDataSo;
// Data
[Title("Indicator Data")]
[SerializeField] private DecalProjector indicator;
[OnValueChanged("ChangeIndicatorType")]
[SerializeField] private EIndicatorType indicatorType;
[field: DisableIf("@true")]
[field: SerializeField] public bool IsCasting { get; set; }
[DisableIf("@true")]
[SerializeField] private bool followMouse;
private Camera mainCam;
private Transform user;
private Collider[] hitColliders;
// Hash
private static readonly int FillHash = Shader.PropertyToID("_Fill");
#endregion
#region Unity built-in methods
private void Awake()
{
InitComponent();
InitData();
}
private void Update()
{
if (followMouse)
{
FollowMouse();
}
}
#endregion
#region Custorm methods
private void InitComponent()
{
indicator = GetComponentInChildren<DecalProjector>();
if (indicator == null)
{
print("하위 오브젝트로 DecalProjector 컴포넌트를 찾을 수 없습니다.");
}
mainCam = Camera.main;
}
private void InitData()
{
ChangeIndicatorType();
BasicSetting();
HideIndicator();
hitColliders = new Collider[activeSkillDataSo.MaxAttackTargets];
}
private void BasicSetting()
{
transform.localPosition = Vector3.zero;
indicator.transform.localScale = new Vector3(activeSkillDataSo.Range, activeSkillDataSo.Range, 1);
indicator.scaleMode = DecalScaleMode.InheritFromHierarchy;
indicator.material.SetFloat(FillHash, 0f);
}
private void ChangeIndicatorType()
{
if (activeSkillDataSo.Indicator != null)
{
indicator.material = activeSkillDataSo.Indicator;
return;
}
switch (indicatorType)
{
case EIndicatorType.NONE:
indicator.material = null;
break;
case EIndicatorType.RADIUS:
indicator.material = new Material(skillIndicatorDataSo.RadiusIndicator);
break;
case EIndicatorType.AREA:
indicator.material = new Material(skillIndicatorDataSo.AreaIndicator);
break;
case EIndicatorType.CONE:
indicator.material = new Material(skillIndicatorDataSo.ConeIndicator);
break;
case EIndicatorType.LINE:
indicator.material = new Material(skillIndicatorDataSo.LineIndicator);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private void HideIndicator()
{
indicator.enabled = false;
indicator.material.SetFloat(FillHash, 0);
IsCasting = false;
followMouse = false;
}
private void InterruptIndicator()
{
HideIndicator();
}
public void Execute(LayerMask targetLayer, Vector3 targetPos)
{
switch (indicatorType)
{
case EIndicatorType.NONE:
indicator.material = null;
break;
case EIndicatorType.RADIUS:
StartCoroutine(RadiusSkill(targetLayer, targetPos));
break;
case EIndicatorType.AREA:
break;
case EIndicatorType.CONE:
break;
case EIndicatorType.LINE:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private IEnumerator RadiusSkill(LayerMask targetLayer, Vector3 targetPos)
{
transform.position = targetPos;
indicator.enabled = true;
if (activeSkillDataSo.CastingTime > 0)
{
IsCasting = true;
var castingTime = 1 / activeSkillDataSo.CastingTime;
while (IsCasting && indicator.material.GetFloat(FillHash) < 1f)
{
CastingMove();
var fillValue = indicator.material.GetFloat(FillHash) + Time.deltaTime * castingTime;
indicator.material.SetFloat(FillHash, fillValue);
yield return null;
}
}
else if (activeSkillDataSo.CastingTime == 0)
{
}
// TODO : 터지는 효과 추가하기
HideIndicator();
Array.Clear(hitColliders, 0,activeSkillDataSo.MaxAttackTargets);
var maxSize = Physics.OverlapSphereNonAlloc(transform.position, activeSkillDataSo.Range, hitColliders, targetLayer);
for (var i = 0; i < maxSize; i++)
{
var iDamageable = hitColliders[i].GetComponent<IDamageable>();
iDamageable.TakeDamage(activeSkillDataSo.Damage);
}
}
private void CastingMove()
{
switch (activeSkillDataSo.CastingType)
{
case 0:
break;
case 1:
break;
case 2:
transform.position = user.position;
break;
}
}
protected void FollowMouse()
{
var ray = mainCam.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var raycastHit, 2000))
{
var userPos = user.position;
var targetPos = (userPos + raycastHit.point) / 2;
var distance = targetPos - userPos;
distance = Vector3.ClampMagnitude((distance * 2), activeSkillDataSo.Range);
indicator.transform.position = userPos + distance;
}
}
public ActiveSkillData GetActiveSkillData() => activeSkillDataSo;
public void SetUser(Transform value) => user = value;
#endregion
2023-10-31 07:37:23 +00:00
}
}