[VR] GroundZero 개발

[4Idle - Gazzlers] 플레이어 오른손 기능 구현(총 쏘기+ 데미지 텍스트 효과)

meltingmelvin 2023. 11. 21. 18:09

오른손 기능

RT-Shoot

RT - 총 발사

=> 오른손의 Index Trigger를 누르는 동안 플레이어가 들고있는 총에서 레이저 샷을 정면으로 발사시킨다.

(이 때, 완전한 정면이 아니라 포물선을 그리며 약간 아래방향으로 날아가게 된다.)

-총구에서 레이저 빔이 날아가는 것으로, 레이저 빔의 끝부분에서 충돌처리가 일어난다.

 

레이저 모델 생성

 

-임의로 총 모델 대신 큐브를 사용하여 넣어주고, 오른손의 자식으로 ShootTrans를 빈 오브젝트로 생성해주었다.

-생성한 ShootTrans를 RightHandController의 Shoot Trans로 할당하였다. 레이저가 발사되는 위치이다.

-RIghtHandController는 오른손 오브젝트에 부착한다. 

-gunLaserGo는 생성될 레이저빔 프리팹을 넣어준다.

-생성된 레이저 빔은 오른손의 index Trigger를 누를때에만 SetActive(true)가 된다.

-총 모델을 변경한 후 결과를 확인해주었다. 

 

 

총 발사 충돌처리

 

-이제 총이 쏴질 때 충돌처리를 해주어야한다. 현재는 레이저 모델만 보여질뿐, 실제로 충돌처리는 하고있지 않다.

-충돌처리를 위해 Ray를 사용할 것이다.

 

-Layer에 Monster를 추가하고, 테스트용 캡슐 오브젝트의 layer를 몬스터로 설정해주었다.

 

-타격된 물체는 흰 막같은게 생기는 것과 동시에 데미지 텍스트가 띄워지면서 플레이어에게 타격되고 있다는 정보를 준다.

=> 먼저 타격 이펙트부터 생성한다.

타격 이펙트 생성

타격 이펙트 생성

-타격 이펙트는 Start할때 생성해두고 필요할때 껐다 켰다 하도록한다.

=> 만약 여러개의 타격 이펙트가 필요해지면 오브젝트 풀링을 사용해 코드를 수정할 예정이다.

-충돌 지점까지만 레이저 빔이 생성되어야 하므로 ParticleSystemRenderer.lenthScale을 조절해주었다. 

-hit.distance값을 lengthScale에 넣어주면 충돌되는 지점까지의 거리만큼만 생성된다.

타격시 이펙트 생성 및 타격된 지점까지만 레이저 생성 결과

-플레이어가 타고있는 탈것에는 타격되더라도 이펙트가 표시되지 않도록 하기 위해 코드 수정

Gazzlers의 몬스터 타격 장면

타격 시 데미지 텍스트 생성

- 몬스터가 타격되면 데미지 텍스트가 띄워져야 한다. 또한 몬스터는 HP Bar가 존재한다.

- 데미지 텍스트는 UI이다. 따라서 캔버스 안에 존재한다.

- UI는 캔버스 안에있고, 데미지 텍스트가 보여져야 할 위치는 World좌표이므로 이 둘의 서로 다른 좌표 체계에 대해 고려해야 한다.

=> 예를 들어 몬스터가 움직이고 있더라도, 몬스터의 위치에 따라서 UI의 위치도 변경되어야한다.

-캔버스의 이름을 WorldCanvas로 변경한다.  World캔버스는 Render Mode 가 WorldSpace이다.

-WorldCanvas의 자식으로 HPBar 오브젝트와 DamageText오브젝트를 생성해준다.

-생성한 두 오브젝트는 프리팹으로 만들고, 씬에서는 없애도로한다.

-새로운 캔버스를 추가해 EnemyCanvas라 명명해두고, RenderMode는 Overlay가 되도록한다.

 

- Enemy 오브젝트에 EnemyController.cs를 새로 생성해 넣어준다.

- EnemyController 스크립트는 Player로부터 GetHit 상태가 되는지 확인하는 역할을 한다.

- 방금 프리팹으로 만들어둔 HPBar가 생성되게 될 위치로 Enemy의 자식으로 빈 오브젝트를 생성해 HPBarPos라 했다.

=> 이 HPBarPos는 월드상의 좌표를 UI상의 캔버스 좌표로 변환해야한다.

좌표 변환이 잘 되는지 확인하기 위해 HPBar가 위치를 잘 받는지 먼저 만들어보았다.

https://docs.unity3d.com/ScriptReference/Camera.WorldToScreenPoint.html

 

Unity - Scripting API: Camera.WorldToScreenPoint

Success! Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable. Close

docs.unity3d.com

 

Camera.WorldToScreenPoint

-RectTransformUtility를 사용해 월드 포인트를 스크린 포인트로 변경할 수 있다.

 

 

https://docs.unity3d.com/ScriptReference/RectTransformUtility.ScreenPointToLocalPointInRectangle.html

 

Unity - Scripting API: RectTransformUtility.ScreenPointToLocalPointInRectangle

The cam parameter should be the camera associated with the screen point. For a RectTransform in a Canvas set to Screen Space - Overlay mode, the cam parameter should be null. When ScreenPointToLocalPointInRectangle is used from within an event handler that

docs.unity3d.com

-Documentation에 따르면 카메라는 null이어도 되므로 할당하지않았고, 위에서 EnemyCanvas를 Overlay로 설정해준것은 이 API때문이다.

 

 

-EnemyController에서 미리 hpBar프리팹을 생성해두되, UpdateHPBarPos 메서드를 통해 위치가 변경되도록 코드를 작성하였다.

-RectTransformUtility.WorldToScreenPoint와 RectTransformUtility.ScreenPointToLocalPointInRectangle을 사용해 좌표 위치를 받는다.

-EnemyController에 다음과 같이 할당한다.

 

 

hpBar가 hpBarPos에 따라 위치를 받아 같이 움직이는 것 확인

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

=> ㅋㅋ이건 overlay로 했을 때 라서, 3d 프로젝트할때 overlay모드 카메라의 경우 이렇게 하면 되지만 오큘러스의 경우 world Space를 사용해야하므로 이것이 필요하지 않다. 그러나 overlay일때는 사용해야하므로 참고해두자.

https://www.youtube.com/watch?v=Bgt90Gu305c&list=PLTFRwWXfOIYA5sIfnHL78hlTU-jwcTLA6&t=217s

https://haseungbong.blogspot.com/2018/10/worldtoscreenpos-in-ugui.html

https://tsubakit1.hateblo.jp/entry/2018/10/16/231300

 

【Unity】ECSでチャンク単位のバッチ処理を実現するChunk Iteration、それとEntityQuery - テラシュール

最近のECS界隈で特に理由もなくChunk Iterationを採用されている事をよく見るので、今回そのChunk Iterationついて書いてみます。 ComponentDataの組み合わせの爆発 Chunk Iterationという回避方法 コードを

tsubakit1.hateblo.jp

-hpBar 프리팹의 사이즈를 적절히 바꿔주고, 기존에 작성한 코드를 간단히 고쳤다. world  Space므로 따로 월드좌표로 변환하지 않아도 된다.

 

데미지 텍스트 구현

-이제 hpBar에서 위치를 받은것을 참고해 타격 위치에 DamageText 프리팹이 타격될때마다 나타나게 구현하면된다.

RightHandController에서 hit한 경우 EnemyController에 전달하기위해 대리자 호출

 

-인수가 1개(매개변수로 Vector3를 받는)대리자를 호출하여 EnemyController에서 적이 타격된것을 알게 하였다.

 

EnemyController에서 Hit된것을 알면 데미지 텍스트를 띄운다.

-DamageText 프리팹의 크기도 적절히 조절해주었다.

-EnemyController에서 hit된 상태인 것을 전달받으면 데미지 텍스트를 띄우도록 코루틴함수를 생성하였다.

-데미지 텍스트 오브젝트는 start할때 생성해두어 false해두었다가, Hit될때마다 코루틴을 호출해 0.3초동안 활성화되도록하였다.

 

 

데미지 텍스트 생성

 

-이제 데이터를 생성해서 UI와 연결해줄 필요가 있다. 다음 포스팅에서 정리할 것이다.