0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

マウスポインターをコライダー内部に閉じ込める方法

Last updated at Posted at 2021-02-24

コライダー判定のPhysics.Raycastは”コライダー内部にある”という判定はしてくれますが、コライダーから見て外部のどこにあるのか?という判定はしてくれません。なのでコライダー内部にマウスポインターを留めたいというときにはちょっと工夫が必要です。

まず、平面(Plane)とRayとの交差する点を取得するコードを組みます
(これもなぜかUnityに標準で備わっていない)
Planeで交差点を取得するには

    //Planeで取得
    public static Vector3 CrossPointOnPlane(Plane plane, Ray ray)
    {
        float enter = 0.0f;
        plane.Raycast(ray, out enter);

        return ray.GetPoint(enter);
    }

平面と交差する点を求められない訳がないとは思いましたが、直接取得する関数がないだけでした

CrossPointOnPlane

    //平面上の点PlanePointと法線PlaneNormalで取得
    public static Vector3 CrossPointOnPlane(Vector3 PlaneNormal, Vector3 PlanePoint, Ray ray, float distance = 1000.0f)
    {
        Vector3 result = Vector3.zero;

        Vector3 v1 = ray.origin - PlanePoint;
        Vector3 v2 = ray.origin + (ray.direction * distance) - PlanePoint;

        float d1 = Mathf.Abs(Vector3.Dot(v1, PlaneNormal));
        float d2 = Mathf.Abs(Vector3.Dot(v2, PlaneNormal));

        float denom = d1 + d2;
  
        if (denom > 0)
        {
            result = ray.GetPoint(distance / denom * d1);
        }
        return result;
    }

これを利用して

pointerPositionInClosedCollider
    public Vector3 pointerPositionInClosedCollider(Camera camera, Collider collider, Vector3 normal)
    {
        Vector3 pointerPosition = Vector3.zero;

        Ray ray = camera.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        bool isInCollider = Physics.Raycast(ray, out hit, 100);
        if (isInCollider)
        {
            pointerPosition = hit.point;
        }
        else
        {
            Vector3 CrossRayPointOnPlane = Calc.CrossPointOnPlane(normal, collider.transform.position, ray, 100.0f);
            pointerPosition = collider.ClosestPoint(CrossRayPointOnPlane);
        }

        return pointerPosition ;
    }

カメラとコライダーとのRayとRaycastHitをとり、コライダー範囲内にカーソルがある場合はRaycastHit.pointを返し、そうでない場合はコライダーを中心とした任意の法線を持つ平面にしたがってコライダー内部にぴったり張り付いて動くポインターが出来上がります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?