평타도 일종의 스킬이다. LC(마우스 좌클릭)시 지정된 위치로 클레어의 손에서 광선이 나간다.
-CrossHair에서 쏜 Ray의 위치의 HitPoint를 받아 그 point를 향해 클레어의 손에서 광선이 나가도록(새로운 Ray를 손에서 => 받은 hitPoint 방향으로 생성)하면 된다.
-즉 카메라에서 나오는 Ray1, 손에서 나오는 Ray2라고 생각하자.
-손에서 나가는 광선이 CrossHair에서 생성된 Ray의 Hitpoint 방향으로 생성되는 코드를 작성후 확인했다.
-잘 생성된다. 다만, 에임이 캐릭터를 통과할때는 이상한 방향으로 생성되는 문제가 생겼다. 이는 layerMask와 tag를 사용해 해결하면 된다.(테스트를 위해 layerMask를 주석처리해서 생긴 문제-플레이어 스스로는 colllider가 있지만 스스로에게는 충돌을 확인할 필요가 없다. )
-이 부분에서 생각해야할 문제가있다. "에임은 어떤 상황에 조준되고, 평타는 어떤 조건에서 쓸 수 있는가"의 문제이다.
=>평타는 에임이 조준되지 않는 허공이나 바닥같은 일반 오브젝트에도 쏠 수 있다. 에임은 타격가능한 물체일때 조준되어 플레이어에게 타격가능한 물체임을 알려주는 역할을 한다.
- 타격 가능한 대상은 어떤 것들이 있는가?
=>타워, 상대 팀, 부술 수 있는 상자, 철거반, 센티넬(립), 수호자 등이다.
-평타를 에임이 조준되지 않는 일반 오브젝트에도 쏠 수 있다고 했지만, collider 가 있어도 충돌체크를 하면 안되는 대상이 있다. 바로 플레이어 자신이다.
-layerMask로 에임 조준에 대한 부분 코드 수정을 해야한다. 현재 작성한 코드는 클레어가 Ray 가 충돌하는 모든 물체에 평타를 사용할 수 있도록 layerMask부분을 빼고 충돌 처리하는지만 확인하도록 작성했다. layerMask로 타워나 타격가능 물체일때만 state를 eState.Hit로 바꿔주도록 해야한다.
-이제 Ray2가 생성되는대로 평타를 만들어주면 된다.
-클레어가 좌클릭할때 Ray2를 생성하도록 코드를 수정하였다.
-OnLC는 ClareController에 작성해주었다. 기존에 MouseController에 작성한 ray2에 관한 부분을 옮겨주었다.
-좌측은 hit 가능하도록 레이어를 설정하였으나, 우측의 상자는 에임이 조준되지 않도록 설정하여 잘되는지 확인하였다.
-이펙트를 어떻게 생성되게 해줘야 DrawRay한것처럼 만들 수 있을까 고민했다. 처음에 Prefab으로 생성한 빔을 hitpoint를 향해 손에서 hipoint를 바로보도록 했더니 늘 일정한 길이의 빔이 생성되는 문제가 생겼다. 빔은 hitpoint까지의 거리에 따라 길이가 짧아지거나 길어지게 만들어야한다.
이펙트는 파티클 시스템으로 구현하였다.
-레이의 충돌이 있을때와 없을때로 나누어 없을때에는 hit.point를 바라보는게 아니라 생성될 평타의 위치를 정해주도록했다. 빈오브젝트로 LCPos를 만들어주고, Canvas의 자식으로 넣은뒤에 위치를 수정하였다.
-이 LCPos는 CrossHair와 y축이 동일하며, Canvas의 자식이므로 카메라의 움직임, 즉 에임의 움직임에 영향을 받는다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class ClareController : MonoBehaviour
{
[SerializeField] MouseController mouse;
[SerializeField] private Transform clareHandTrans;
[SerializeField] private GameObject beamGo;
[SerializeField] private GameObject beamImpactGo;
[SerializeField] private LineRenderer lr;
[SerializeField] private Transform LCPos;
[SerializeField] private Transform crossHair;
private GameObject newBeamGo;
private Vector3 moveDir;
private Animator anim;
private Ray ray2;
private RaycastHit hit;
// Start is called before the first frame update
void Start()
{
this.anim = GetComponent<Animator>();
this.newBeamGo = Instantiate<GameObject>(beamGo);
this.beamImpactGo = Instantiate<GameObject>(beamImpactGo);
// this.lr = beamGo.GetComponent<LineRenderer>();
this.newBeamGo.SetActive(false);
this.beamImpactGo.SetActive(false);
lr.enabled = false;
// lr.positionCount = 0;
}
// Update is called once per frame
void Update()
{
if(moveDir != Vector3.zero)
{
if(this.moveDir.z > 0)//forward
{
//this.transform.rotation = Quaternion.LookRotation(moveDir); ;//진행방향으로 회전
this.transform.Translate(Vector3.forward * 4.0f * Time.deltaTime);//이동
if(this.moveDir.x == 0)//forward
{
this.anim.SetInteger("State", 1);//move forward
}
else if (this.moveDir.x > 0)
{
this.anim.SetInteger("State", 2);//move forward rightCross
}
else if (this.moveDir.x < 0)
{
this.anim.SetInteger("State", 4);//move forward leftCross
}
}
else if(this.moveDir.z < 0)//backward
{
this.transform.Translate(this.moveDir * 4.0f * Time.deltaTime);//이동
if (this.moveDir.x == 0)//backward
{
this.anim.SetInteger("State", 3);//move backward
}
else if (this.moveDir.x > 0)
{
this.anim.SetInteger("State", 7);//move backward rightCross
}
else if (this.moveDir.x < 0)
{
this.anim.SetInteger("State", 8);//move backward leftCross
}
}
else
{//stay but press left or right
this.transform.Translate(this.moveDir * 4.0f * Time.deltaTime);//이동
if (this.moveDir.x < 0)
{
this.anim.SetInteger("State", 5);//move left
}
else
{
this.anim.SetInteger("State", 6);//move right
}
}
}
else
{
this.anim.SetInteger("State", 0); //idle
}
}
private IEnumerator CoLCBeam()
{
this.newBeamGo.SetActive(true);
// this.newBeamGo.transform.position = this.ray2.origin;
this.newBeamGo.transform.position = this.clareHandTrans.position;
if (mouse.hit.point != Vector3.zero && mouse.hit.collider.tag != "Player")
{
this.newBeamGo.transform.LookAt(mouse.hit.point);
}
else
{
this.newBeamGo.transform.LookAt(this.LCPos);
}
//this.newBeamGo.transform.Rotate(ray2.direction);
yield return new WaitForSeconds(0.3f);
this.newBeamGo.SetActive(false);
}
private IEnumerator CoBeamImpact()
{
this.beamImpactGo.SetActive(true);
this.beamImpactGo.transform.position = this.hit.point;
yield return new WaitForSeconds(0.3f);
this.beamImpactGo.SetActive(false);
}
private IEnumerator CoLCLineRenderer()
{
lr.enabled = true;
lr.SetPosition(0, clareHandTrans.position);
Vector3 LCPos = new Vector3(this.LCPos.position.x, this.LCPos.position.y, this.LCPos.position.z);
Debug.Log(this.transform.forward);
lr.SetPosition(1, LCPos);
yield return new WaitForSeconds(0.3f);
lr.enabled = false;
}
public void OnMove(InputAction.CallbackContext ctx)
{
Vector2 dir = ctx.ReadValue<Vector2>();
this.moveDir = new Vector3(dir.x, 0,dir.y);//2차원 좌표를 3차원 좌표로 변환
}
public void OnLC(InputAction.CallbackContext ctx)
{
Vector3 ray2Direction;
if (mouse.hit.point != Vector3.zero )
{
ray2Direction = mouse.hit.point- this.clareHandTrans.position;
}
else
{
ray2Direction = LCPos.position - this.clareHandTrans.position;
}
this.ray2 = new Ray(this.clareHandTrans.position, ray2Direction);
float lcDistance = 5f;
if (Physics.Raycast(this.ray2.origin, this.ray2.direction, out hit, lcDistance) && !hit.collider.CompareTag("Player"))
{
// Debug.LogFormat("LC Hit! Distance : {0}", hit.distance);
Debug.DrawRay(this.ray2.origin, this.ray2.direction * lcDistance, Color.yellow, 0.5f);
StartCoroutine(this.CoBeamImpact());
}
StartCoroutine(this.CoLCBeam());
// StartCoroutine(this.CoLCLineRenderer());
}
}
'[3D] Cyphers 모작' 카테고리의 다른 글
[Cyphers] 클레어 클렌징빔 오브젝트 구현 (1) | 2023.10.05 |
---|---|
[Cyphers] 클레어 평타 수정(particleSystem Renderer LengthScale) (0) | 2023.10.04 |
[Cyphers] 에임 조준(CrossHair) (0) | 2023.09.27 |
[Cyphers] 에임 - CrossHair 생성, 마우스에 따른 캐릭터 회전 (0) | 2023.09.26 |
[Cyphers] Player 이동구현(New Input System) + 카메라 컨트롤 (0) | 2023.09.25 |