4-10. 2조 포탈

keubung·2024년 11월 7일

포탈 이동

- 포탈 간의 이동을 구현할 때 자연스러운 이동을 위해 이동되는 위치를 포탈과 겹쳐 두었는데 이로인해 이동을 했을 때 들어왔던 포탈과 나가는 포탈 간의 이동이 제대로 되지 않는 문제가 있었음.

  • 해결 방법
  1. PortalableObject스크립트에서 객체가 포탈 내에 있는지 확인하는 inPortalCount 변수로 객체가 포탈을 진입할 때 SetIsInPortal() 메서드에서 이 카운트가 증가하고, ExitPortal() 메서드에서 객체가 포탈을 나가면 감소하도록 하여 중복 진입을 방지

    public void SetIsInPortal(Portal inPortal, Portal outPortal, Collider wallCollider)
    {
        this.inPortal = inPortal;
        this.outPortal = outPortal;
    
        Physics.IgnoreCollision(collider, wallCollider);
    
        cloneObject.SetActive(false);
    
        ++inPortalCount;
    }
    
    public void ExitPortal(Collider wallCollider)
    {
        Physics.IgnoreCollision(collider, wallCollider, false);
        --inPortalCount;
    
        if (inPortalCount == 0)
        {
            cloneObject.SetActive(false);
        }
    }
  2. Physics.IgnoreCollision(collider, wallCollider)는 객체가 포탈 벽과의 충돌을 무시하게 설정. 이는 객체가 포탈을 통과할 때 다시 충돌하거나 되돌아가는 것을 방지.

    public void SetIsInPortal(Portal inPortal, Portal outPortal, Collider wallCollider)
    {
        this.inPortal = inPortal;
        this.outPortal = outPortal;
    
        Physics.IgnoreCollision(collider, wallCollider);
    
        cloneObject.SetActive(false);
    
        ++inPortalCount;
    }
  3. Warp()에서 두 포탈을 inPortal과 outPortal로 주어 객체가 포탈을 통과하면 inPortal이 이제 outPortal이 되고, 객체가 나왔던 포탈은 inPortal로 변경.

     public virtual void Warp()
     {
         var inTransform = inPortal.transform;
         var outTransform = outPortal.transform;
    
         Vector3 relativePos = inTransform.InverseTransformPoint(transform.position);
         relativePos = halfTurn * relativePos;
         transform.position = outTransform.TransformPoint(relativePos);
    
         Quaternion relativeRot = Quaternion.Inverse(inTransform.rotation) * transform.rotation;
         relativeRot = halfTurn * relativeRot;
         transform.rotation = outTransform.rotation * relativeRot;
    
         Vector3 relativeVel = inTransform.InverseTransformDirection(rigidbody.velocity);
         relativeVel = halfTurn * relativeVel;
         rigidbody.velocity = outTransform.TransformDirection(relativeVel);
    
         var tmp = inPortal;
         inPortal = outPortal;
         outPortal = tmp;
     }

- 포탈이 생성될 때 생성되는 벽면의 각도와 상관없이 y축에 평행하게 세워진 상태로 포탈이 생성되는 문제가 있었음.

  • 해결 방법
    레이캐스트와 닿는 벽면의 법선을 이용하여 포탈 생성
     var cameraRotation = cameraMove.TargetRotation;
     var portalRight = cameraRotation * Vector3.right;
    
     if (Mathf.Abs(portalRight.x) >= Mathf.Abs(portalRight.z))
     {
         portalRight = (portalRight.x >= 0) ? Vector3.right : -Vector3.right;
     }
     else
     {
         portalRight = (portalRight.z >= 0) ? Vector3.forward : -Vector3.forward;
     }
    
     var portalForward = -hit.normal;
     var portalUp = -Vector3.Cross(portalRight, portalForward);
    
     var portalRotation = Quaternion.LookRotation(portalForward, portalUp);

  • 아직 포탈에 서로의 공간이 보이는 카메라 설정이 제대로 되지 않았음. 추후에 추가해볼 예정.
profile
김나영(Unity_6기)

0개의 댓글