+ 전투 플레이어도 피격시 FlashWhite 기능이 추가되었습니다. + 전투 플레이어의 기본 속도 10 -> 7로 변경했습니다. + 보스 및 잡몹의 Collider를 통과할 수 있게 변경했습니다. + 보스의 스킬에 피격되면 튕겨내는 기능을 추가했습니다. + 코뿔소 스킬(EarthquakeWave)가 표시하는 것과 다르게 공격하는 오류를 수정했습니다.
145 lines
5.9 KiB
C#
145 lines
5.9 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Sirenix.OdinInspector;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
// ReSharper disable once CheckNamespace
|
|
namespace BlueWaterProject
|
|
{
|
|
public class ParticleWeapon : MonoBehaviour
|
|
{
|
|
[Serializable]
|
|
public class ImpactParticleInfo
|
|
{
|
|
public GameObject impactParticle;
|
|
public LayerMask layer;
|
|
}
|
|
|
|
public List<ImpactParticleInfo> impactParticleInfoList = new();
|
|
//public GameObject impactParticle; // Effect spawned when projectile hits a collider
|
|
public GameObject projectileParticle; // Effect attached to the gameobject as child
|
|
public GameObject muzzleParticle; // Effect instantly spawned when gameobject is spawned
|
|
[Header("Adjust if not using Sphere Collider")]
|
|
public float colliderRadius = 1f;
|
|
[Range(0f, 1f)] // This is an offset that moves the impact effect slightly away from the point of impact to reduce clipping of the impact effect
|
|
public float collideOffset = 0.15f;
|
|
|
|
[Title("Extensions Data")]
|
|
[SerializeField] private LayerMask targetLayer;
|
|
[SerializeField] private bool useAutoDestroy = true;
|
|
[ShowIf("@useAutoDestroy")]
|
|
[SerializeField] private float autoDestroyTime = 5f;
|
|
|
|
public UnityEvent<RaycastHit, float, GameObject> onHitAction;
|
|
|
|
private GameObject marker;
|
|
private float power;
|
|
private float detectionDistance;
|
|
|
|
public Rigidbody Rb { get; private set; }
|
|
private SphereCollider sphereCollider;
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
var radius = sphereCollider ? sphereCollider.radius : colliderRadius;
|
|
var direction = Rb ? Rb.velocity.normalized : transform.forward;
|
|
|
|
Gizmos.color = Color.red;
|
|
Gizmos.DrawWireSphere(transform.position, radius); // Draws the start sphere
|
|
Gizmos.DrawLine(transform.position, transform.position + direction * detectionDistance); // Draws the path of the SphereCast
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
Rb = GetComponent<Rigidbody>();
|
|
sphereCollider = GetComponent<SphereCollider>();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
if (useAutoDestroy)
|
|
{
|
|
Destroy(gameObject, autoDestroyTime);
|
|
}
|
|
|
|
projectileParticle = Instantiate(projectileParticle, transform.position, transform.rotation) as GameObject;
|
|
projectileParticle.transform.parent = transform;
|
|
if (muzzleParticle)
|
|
{
|
|
muzzleParticle = Instantiate(muzzleParticle, transform.position, transform.rotation) as GameObject;
|
|
Destroy(muzzleParticle, 1.5f); // 2nd parameter is lifetime of effect in seconds
|
|
}
|
|
}
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
if (Rb.velocity.magnitude != 0)
|
|
{
|
|
transform.rotation = Quaternion.LookRotation(Rb.velocity); // Sets rotation to look at direction of movement
|
|
}
|
|
|
|
float radius; // Sets the radius of the collision detection
|
|
if (sphereCollider)
|
|
radius = sphereCollider.radius;
|
|
else
|
|
radius = colliderRadius;
|
|
|
|
var direction = Rb.velocity; // Gets the direction of the projectile, used for collision detection
|
|
if (Rb.useGravity)
|
|
direction += Physics.gravity * Time.deltaTime; // Accounts for gravity if enabled
|
|
direction = direction.normalized;
|
|
|
|
detectionDistance = Rb.velocity.magnitude * Time.deltaTime; // Distance of collision detection for this frame
|
|
|
|
if (Physics.SphereCast(transform.position, radius, direction, out var hit, detectionDistance, targetLayer)) // Checks if collision will happen
|
|
{
|
|
transform.position = hit.point + (hit.normal * collideOffset); // Move projectile to point of collision
|
|
|
|
GameObject impactP = null;
|
|
foreach (var element in impactParticleInfoList)
|
|
{
|
|
if ((element.layer & (1 << hit.collider.gameObject.layer)) == 0) continue;
|
|
|
|
impactP = Instantiate(element.impactParticle, transform.position, Quaternion.FromToRotation(Vector3.up, hit.normal));
|
|
break;
|
|
}
|
|
|
|
var trails = GetComponentsInChildren<ParticleSystem>(); // Gets a list of particle systems, as we need to detach the trails
|
|
//Component at [0] is that of the parent i.e. this object (if there is any)
|
|
for (var i = 1; i < trails.Length; i++) // Loop to cycle through found particle systems
|
|
{
|
|
var trail = trails[i];
|
|
|
|
if (trail.gameObject.name.Contains("Trail"))
|
|
{
|
|
trail.transform.SetParent(null); // Detaches the trail from the projectile
|
|
Destroy(trail.gameObject, 2f); // Removes the trail after seconds
|
|
}
|
|
}
|
|
|
|
if (onHitAction.GetPersistentEventCount() <= 0)
|
|
{
|
|
var iDamageable = hit.transform.GetComponent<IDamageable>();
|
|
iDamageable?.TakeDamage(power);
|
|
}
|
|
else
|
|
{
|
|
onHitAction.Invoke(hit, power, marker);
|
|
}
|
|
|
|
Destroy(projectileParticle, 3f); // Removes particle effect after delay
|
|
if (impactP)
|
|
{
|
|
Destroy(impactP, 3.5f); // Removes impact effect after delay
|
|
}
|
|
Destroy(gameObject); // Removes the projectile
|
|
}
|
|
}
|
|
|
|
|
|
public void SetPower(float value) => power = value;
|
|
public void SetHitMarker(GameObject value) => marker = value;
|
|
}
|
|
} |