본문 바로가기
마블 VR 프로젝트 제작

[마블 VR] 공중적 레이저 발사/방패 막기 버그 수정

by 노재두내 2023. 12. 12.

문제점1. 방패가 적을 연속 공격하고 돌아와서 엄청 흔들림

 

 private IEnumerator CoDetectEnemy()
    {
        while (true)
        {
            Collider[] enemyCols = Physics.OverlapSphere(this.transform.position, this.detectRadius, 1 << 6);
            this.dic.Clear();
            for (int i = 0; i < enemyCols.Length; i++)
            {
                var col = enemyCols[i];
                this.dic.Add(col.gameObject, Vector3.Distance(col.transform.position, this.transform.position));
            }

            if (this.dic.Count > 0)
            {
                Debug.Log(dic.Count);
                var nearestDistance = this.dic.Values.Min();
                var target = this.dic.FirstOrDefault(x => x.Value == nearestDistance).Key;
                var dirTarget = target.transform.position - this.transform.position;
                Ray ray = new Ray(this.transform.position, dirTarget);
                Debug.DrawRay(ray.origin, ray.direction * 1000f, Color.red);
                this.pos.Translate(ray.direction * this.moveSpeed * Time.fixedDeltaTime, Space.World);

                Quaternion rotation = Quaternion.LookRotation(ray.direction, Vector3.forward);
                this.pos.transform.localRotation = rotation;
            }
            else
            {
                Debug.Log("방패가 왜자꾸 흔들리니");
                dir = (this.lHandAnchor.position-this.pos.position).normalized;
                this.pos.Translate(dir * this.moveSpeed * Time.fixedDeltaTime, Space.World);
            }
            yield return null;
        }
    }

적 감지하는 부분의 else (적이 더이상 없다면) 이부분이 계속 호출돼서 문제일거같아서 로그를 찍어봤다 .

역시나 많이 찍히는군..

stopcoroutine을 했는데 왜그러지? stopcoroutine이 안됐나 거기에도 로그를 찍어보자 

 

되고는 있는데 collisionEnter할때 이다 보니까 마지막이 코루틴 정지가 아니고 감지하는 코루틴이 실행된다.

그래서 맞고 돌아오면 break를 해줬다. 잘 돌아가긴 하지만 문제가 없으려나 ? 싶기도 하다


문제점2. 멈추는 현상 Again..

매우매우매우 이상

 

예전에 겪었던 문제와똑같이 겪고 있다 . 그때는 ray.direction으로 바꾸니가 잘 동작했는데 이번엔 ray.direction이 맞는데도 그런다. 두개까진 괜찮은데 세개부터 이상한 이유가 뭘까 ..

break가 문제인가 싶어서 주석걸었지만 그것도 아니다.

감지는 잘 하고 있다..분명히

 

방향이 계속 바껴서 이상한거야 그렇다 치고 세번째에선 대체 왜 멈추는건지 알수가 없다.. 

 

 

collider를 감지하고 있어서 유니티 생명주기 때문에 collider가 꺼지기 전에 감지를 하고 있어서 그런가 해서 

trigger로도 바꿔보고 별 짓 다해봤는데 아니었음 

며칠을 고민했는데 translate의 방향이 자꾸만 바껴서 멈추는건가 싶었다.

그래서 방향을 부딪힐때마다 한번만 바뀌게 설정

 private void OnCollisionEnter(Collision collision)
    {
        this.StartCoroutine(CoDetectEnemy());
        this.colliderTrans = this.pos.transform.position;
    }
    private IEnumerator CoDetectEnemy()
    {
        this.colliderTrans = this.pos.transform.position;
        while (true)
        {
            Collider[] enemyCols = Physics.OverlapSphere(this.transform.position, this.detectRadius, 1 << 6);
            this.dic.Clear();
            for (int i = 0; i < enemyCols.Length; i++)
            {
                var col = enemyCols[i];
                this.dic.Add(col.gameObject, Vector3.Distance(col.transform.position, this.transform.position));
            }

            if (this.dic.Count > 0)
            {
                Debug.Log(dic.Count);
                var nearestDistance = this.dic.Values.Min();
                var target = this.dic.FirstOrDefault(x => x.Value == nearestDistance).Key;
                var dirTarget = (target.transform.position - colliderTrans).normalized;
               
                
                Ray ray = new Ray(this.pos.transform.position, dirTarget);
                Debug.DrawRay(ray.origin, ray.direction * 1000f, Color.red);

                this.pos.transform.LookAt(target.transform);
                Debug.Log(ray.direction);
                this.pos.Translate(ray.direction * this.moveSpeed * Time.fixedDeltaTime, Space.World);
            }
            else
            {
                dir = (this.centerEyeAnchor.position - this.pos.position).normalized;
                this.pos.Translate(dir * this.moveSpeed * Time.fixedDeltaTime, Space.World);
                break;
            }
            yield return null;
        }
    }

하지만 멈추는 현상은 없어졌지만 제대로 동작하지 않는다 그때의 방향이 다음 적으로 가기에 맞지 않는듯 싶었다.

 

 

=> 그래서 translate말고 moveTowards로 변경했다.

this.pos.transform.position = Vector3.MoveTowards(this.pos.transform.position, target.transform.position, 10f * Time.fixedDeltaTime);

 

이제 적도 잘 맞추고 멈추지 않고 돌아온다. 

하지만 돌아올때가 이상함

 

 

pos는 0으로 초기화 되는데 shield의 위치가 이상해져있었음

if (isGrab == true)
        {
            this.pos.transform.position = Vector3.MoveTowards(this.pos.transform.position, lHandAnchor.position, 10f * Time.deltaTime);
            if (this.pos.transform.position == lHandAnchor.position)
            {
                this.pos.SetParent(lHandAnchor);
                this.pos.localPosition = new Vector3(0, 0, 0);
                this.pos.localRotation = Quaternion.Euler(0, 0, 0);
                this.transform.localPosition = new Vector3(0, 0, 0);
                this.Init();
                isGrab = false;
                isShoot = false;
            }

        }

 

transform의 위치도 초기화 시키는 코드를 짜니까 잘 동작한다.

-> 아님 안됨

-> 부딪히고 왔을때만 그런 현상이 있다.

freeze position을 모두 체크 해주니 제대로 동작한다.

 

 

==> 나중에 오큘러스로 실행해보니 해결 안됨 여전히 멈춘다.

알고보니 코루틴이 쌓이고 있어서 그랬다.

stopcouroutine 을 하고 , 적 감지를 부딪힐때마다 하는게 아니라 부딪혔을 때 한번만 감지하도록 했다.

 private void OnCollisionEnter(Collision collision)
    {
        if(collision.gameObject.CompareTag("Enemy"))
        {
            //EditorApplication.isPaused = true;
            collision.gameObject.SetActive(false);
            Debug.Log("<color=yellow>=> 충돌됨</color>");

            if (this.moveCoroutine != null) this.StopCoroutine(this.moveCoroutine);
            if (this.moveToEnemyRoutine != null) this.StopCoroutine(this.moveToEnemyRoutine);

            var target = this.FindNextTarget();
            if (target != null)
            {
                Debug.Log("<color=yellow>=> 타겟이 있음</color>");
                Debug.DrawLine(this.transform.position, target.transform.position, Color.red, 10f);

                this.RotateShield(target);
                this.moveToEnemyRoutine = this.StartCoroutine(this.CoMoveToEnemy(target.transform));
            }
            else  // 모든 적을 맞추고 타겟이 없음
            {
                Debug.Log("<color=yellow>=> 타겟이 없음</color>");
                //되돌아옴 
                this.moveCoroutine = this.StartCoroutine(this.CoMove());
                //this.RotateShield(null);
            }
        }
        else //부딪힌게 enemy가 아님
        {
            dir = (this.lHandAnchor.position - this.pos.position).normalized;
        }
    }

 
    private GameObject FindNextTarget()
    {
        Collider[] enemyCols = Physics.OverlapSphere(this.pos.transform.position, this.detectRadius, 1 << 6);
        this.dic.Clear();
        for (int i = 0; i < enemyCols.Length; i++)
        {
            var col = enemyCols[i];
            this.dic.Add(col.gameObject, Vector3.Distance(col.transform.position, this.pos.transform.position));
        }

        if (this.dic.Count > 0)
        {

            Debug.Log(dic.Count);
            var nearestDistance = this.dic.Values.Min();
            var target = this.dic.FirstOrDefault(x => x.Value == nearestDistance).Key;
            return target;
        }
        else
        {
            dir = (this.lHandAnchor.position - this.pos.position).normalized;
            return null;
        }

    }


    private Coroutine moveToEnemyRoutine;

    //두번째 부터 사용 
    private IEnumerator CoMoveToEnemy(Transform target)
    {
        Debug.Log("<color=yellow>=> CoMoveToEnemy</color>");

        while (true) {

            var dir = (target.transform.position - this.pos.position).normalized;

            DrawArrow.ForDebug(this.pos.transform.position, dir, 10f, Color.red, ArrowType.Solid);

            this.pos.transform.Translate(dir * this.moveSpeed * Time.deltaTime, Space.World);

            var dis = Vector3.Distance(this.pos.transform.position, target.transform.position);
            if(dis <= 0.1f)
            {
                break;
            }
            yield return null;
        }
        Debug.Log("<color=yellow>=> 이동완료</color>");

    }

 

이제 완전히 속도도 일정하게 제대로 동작한다!


문제점3. 여기의 레이저가 공중적 하나의 레이저만 받아와서 두마리 이상이면 오류가 난다. 그래서 다른 공중적의 laser(ray를 쏴서 방패와 부딪히는지 검사하는 스크립트) 를 비활성화 시키면 방패가 laser를 비활성화 시킨 공중적의 레이저에는 진동하지 않는다.

 

수정

using Oculus.Interaction.HandGrab;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;

public class EnemyAttackMain : MonoBehaviour
{ 
    private Laser[] lasers;
    [SerializeField]
    private Shield shield;
    [SerializeField]
    private Button btnEnemy;
    [SerializeField]
    private GameObject aerialEnemyPrefab;
    [SerializeField]
    private Transform[] points;

    void Start()
    {
        
        this.btnEnemy.onClick.AddListener(() =>
        {
            this.lasers = GameObject.FindObjectsOfType<Laser>();
            
            foreach (Laser laser in lasers)
            {
                laser.onGetHit = () =>
                {
                    this.shield.Shake();
                };
            }
            foreach (Laser laser in lasers)
            {
                laser.onStopGetHit = () =>
                {
                    this.shield.StopShake();
                };
            }
        });

    }
}

다른 문제점 

바닥에 맞아도 적 감지해서 공격하고 돌아옴

혹시 몰라서 다시 

 private void OnCollisionEnter(Collision collision)
    {
        if(collision.gameObject.CompareTag("Enemy"))
        {
            this.StartCoroutine(CoDetectEnemy());
        }
        else
        {
            dir = (this.lHandAnchor.position - this.pos.position).normalized;
        }
    }

잘 동작한다.. 어이없을 무

이제 바닥 맞으면 바로 돌아오고, 적에 맞으면 적 때리고 돌아온다.

 


적의 위치에 따라 방패의 각도 조절하기

전에도 시도 했었는데 실패 했어서 다시 도전한다..

먼저 테스트로 큐브를 타겟으로 하고 쉴드가 큐브를 어떻게 쳐다보는지 확인해봤다.

this.transform.rotation = Quaternion.LookRotation(this.lookTarget.position - this.transform.position);

여기서 타겟은 큐브임

여기서 확인해보니 방패의 위쪽이 쳐다보는걸 확인할 수 있다.

하지만 내가 원하는건 이게 아니다..

this.transform.rotation = Quaternion.LookRotation(this.lookTarget.position - this.transform.position,Vector3.up);

마지막 인자로 Vector3.up을 쓰던 , Vector3.left, Vector3.down을 쓰던 다 방패의 위쪽이 큐브를 쳐다본다. 

그래서 pos를 돌리기로 했다.

오 쒯 찾았당.

this.pos.transform.rotation = Quaternion.LookRotation(this.lookTarget.position - this.pos.transform.position,Vector3.right);

역시 pos가 정답이었다.

 

이제 적을 보도록 코드를 짜고 해보자

응 안돼.

겁나 이상함

왜 아까처럼 쳐다보지 않는거니

아 방향이 좀 이상한거같기도 하고..

 

다음 게시물에 이어서 계속..