Laser redirected through portal

Hi, I make Portal game for AR and I can’t solve this problem.
I want redirected laser through portal to second portal (Image 1)

public void ReflectLaser(RaycastHit hit, Transform laserStartPosition)
{
    Vector3 laserDirect = laserStartPosition.position - hit.point;
    Vector3 portalDirect = transform.position - hit.point;
    
    float angle = Vector3.Angle(laserDirect, Vector3.forward);
    
    GameObject point = new GameObject();
    point.transform.position = otherPortal.GetComponentInChildren<Portal>().laserStartPoint.position - portalDirect;
    otherPortal.GetComponentInChildren<Portal>().SetLaser(point.transform, angle);
}

public void SetLaser(Transform laserTransform, float angle)
{
    laserTransform.rotation = Quaternion.AngleAxis(angle, Vector3.up);

    laser = Instantiate(GameManager.Instance.other.LaserRed);
    laser.SetActive(true);
    laser.GetComponent<Laser>().InitLaser(1, laserTransform);
}

this code works fine when both portals are side by side on one wall, as you can see on second image

Problem is when second portal are placed on surface or somewhere else. Redirected laser has still same direction. Check pic. 3

Please what is wrong with this ?

From what I can see, you’re going off the world forward vector when calculating the angle to feed into your set laser function. As a result, you’ll always have the lasers going in the exact same direction, because they’re both set relative to the global Z-axis. You’ll want to set your angle according to the start point’s forward vector(or the direct laser’s). Switching float angle = Vector3.Angle(laserDirect, Vector3.forward); to float angle = Vector3.Angle(laserDirect, transform.forward); may be all you need. You’ll likely also have to set your rotation in the SetLaser function to work in local space, though.

Just forget about messing with angles. All you need to do is transform your worldspace direction into local space of your entrance portal. Once you have the direction and hit pos in local coordinates, just transform them back to worldspace using your exit portal. So all you need is

var lPos = entranceTransform.InverseTransformPoint(hit.point);
var lDir = entranceTransform.InverseTransformDirection(hit.point - laserStartPosition.position);
lPos.x = -lPos.x;
lPos.z = -lPos.z;
lDir.x = -lDir.x;
lDir.z = -lDir.z;
var outPos = exitTransform.TransformPoint(lPos);
var outDir = exitTransform.TransformDirection(lDir);

Note that the 4 lines in the middle just flip the local position / direction. This assumes that the surface normal of the portals is the z axis of the transforms. It basically does a 180° rotation around the y axis. Note that we assume that the hit position is at the portals surface. Keep in mind that if the hit point is actually “before” the entrance portal, it would be “behind” the exit portal. Though this is the correct relative position anyways.