OldBlueWater/BlueWater/Assets/02.Scripts/Item/ItemController.cs
NTG 899f6cccf4 Closes #161 #169 #170
+ Ui가 화면 밖으로 나갔을 때, 화살표로 ui 표시하는 기능 추가
+ 바다 위에 떠다니는 베릴 오브젝트 및 파괴 기능 추가
+ 코뿔소 에셋 추가
2024-02-05 00:33:41 +09:00

152 lines
5.5 KiB
C#

using System;
using System.Collections;
using Sirenix.OdinInspector;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public class ItemController : MonoBehaviour
{
[Title("아이템")]
[SerializeField] private Item item;
[SerializeField] private GameObject itemUiPrefab;
[SerializeField] private GameObject pointingArrowUiPrefab;
[ShowIf("@pointingArrowUiPrefab")]
[SerializeField] private float arrowOffset = 10f;
[Title("자동 파괴")]
[SerializeField] private bool useAutoDestroy = true;
[ShowIf("@useAutoDestroy")]
[SerializeField] private float autoDestroyTime = 30f;
[Title("획득")]
[SerializeField] private bool drawGizmos = true;
[SerializeField] private float radius = 5f;
[SerializeField] private float acquisitionTime = 1f;
[SerializeField] private LayerMask targetLayer;
private Collider[] hitColliders = new Collider[1];
private Collider targetCollider;
private WaitForSeconds lootCoroutineTime = new(0.5f);
private AudioSource audioSource;
private ItemUiController itemLootUi;
private Transform pointingArrowUi;
private void OnDrawGizmosSelected()
{
if (!drawGizmos) return;
Gizmos.DrawWireSphere(transform.position, radius);
}
public void Init(Item newItem)
{
item = newItem;
var myPos = transform.position;
var screenPos = CameraManager.Inst.MainCam.WorldToScreenPoint(myPos);
itemLootUi = Instantiate(itemUiPrefab, screenPos, Quaternion.identity, UiManager.Inst.OceanUi.ItemsLoot).GetComponent<ItemUiController>();
if (pointingArrowUiPrefab)
{
pointingArrowUi = Instantiate(pointingArrowUiPrefab, screenPos, Quaternion.identity, UiManager.Inst.OceanUi.InstantiateUi).transform;
pointingArrowUi.gameObject.SetActive(false);
}
itemLootUi.Init(transform);
}
private void Awake()
{
audioSource = transform.parent.Find("Audio").GetComponent<AudioSource>();
}
private void Start()
{
if (useAutoDestroy)
{
Destroy(transform.parent.gameObject, autoDestroyTime);
Destroy(itemLootUi.gameObject, autoDestroyTime);
}
StartCoroutine(LootCoroutine());
}
private void LateUpdate()
{
PointingArrowUi();
}
private IEnumerator LootCoroutine()
{
while (true)
{
var maxSize = Physics.OverlapSphereNonAlloc(transform.position, radius, hitColliders, targetLayer);
if (maxSize > 0)
{
targetCollider = hitColliders[0];
itemLootUi.ItemAcquisition();
break;
}
yield return lootCoroutineTime;
}
var startPosition = transform.position;
var elapsedTime = 0f;
while (elapsedTime < acquisitionTime)
{
elapsedTime += Time.deltaTime;
var t = elapsedTime / acquisitionTime;
t = Mathf.SmoothStep(0f, 1f, t);
transform.position = Vector3.Lerp(startPosition, targetCollider.transform.position, t);
yield return null;
}
item.Acquire();
itemLootUi.gameObject.SetActive(false);
UiManager.Inst.OceanUi.DropItemGroupController.ShowDropItemInfoUi(item);
if (audioSource && audioSource.resource)
{
audioSource.Play();
}
yield return new WaitForSeconds(audioSource.clip.length);
Destroy(transform.parent.gameObject);
Destroy(itemLootUi.gameObject);
}
private void PointingArrowUi()
{
if (!itemLootUi || !pointingArrowUi) return;
var planes = GeometryUtility.CalculateFrustumPlanes(CameraManager.Inst.MainCam);
var centerPosition = GameManager.Inst.ShipPlayer.transform.position;
var direction = transform.position - centerPosition;
var ray = new Ray(centerPosition, direction);
var rayMinDistance = Mathf.Infinity;
for (var i = 0; i < 4; i++)
{
if (planes[i].Raycast(ray, out var distance) && distance < rayMinDistance)
{
rayMinDistance = distance;
}
}
rayMinDistance = Mathf.Clamp(rayMinDistance, 0f, direction.magnitude);
pointingArrowUi.gameObject.SetActive(direction.magnitude > rayMinDistance);
var angle = Mathf.Atan2(direction.normalized.z, direction.normalized.x) * Mathf.Rad2Deg;
pointingArrowUi.transform.rotation = Quaternion.Euler(0, 0, angle + 90f);
var screenPosition = CameraManager.Inst.MainCam.WorldToScreenPoint(ray.GetPoint(rayMinDistance));
screenPosition.x = Mathf.Clamp(screenPosition.x, arrowOffset, Screen.width - arrowOffset);
screenPosition.y = Mathf.Clamp(screenPosition.y, arrowOffset, Screen.height - arrowOffset);
pointingArrowUi.transform.position = screenPosition;
}
}
}