Unity 接触イベントのキャスト


### callbackで連れてくる。
```C#
//usage
 colcube.AddComponent<CastScript>();
 colcube.GetComponent<CastScript>().caller = castTrigger ;//
```

```C#
public class CastScript : MonoBehaviour
{
    [SerializeField] public string debug = "";

    //注意：instatntlateで複製した時には、callerは外れるため、再度設定する必要がある。
    public System.Action<Collider, GameObject, string> caller;
    void Awake()
    {
        var co = gameObject.GetComponent<MeshCollider>();
        if (co != null) co.convex = true;
        var co2 = gameObject.GetComponent<Collider>();
        co2.isTrigger = true;
        this.caller = _caller;
    }
    void _caller(Collider other, GameObject go, string timing)
    {
        Debug.Log("dummy:" + go.name + ":" + timing);
    }
    void OnTriggerEnter(Collider other) => caller(other, gameObject, "Enter");
    void OnTriggerStay(Collider other) {/*heavy*/}
    void OnTriggerExit(Collider other) => caller(other, gameObject, "Exit");
}//class

```


### 空のゲームオブジェクトに入れるだけ
```gameboard.cs
using UnityEngine;

public class gameboard : MonoBehaviour
{
    void Start()
    {
        //
        var o = GameObject.CreatePrimitive(PrimitiveType.Plane);
        o.transform.localPosition=new Vector3(0,-0.5f,0);
        o.transform.localScale *= 2;

        //
        var colcube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        colcube.name = "colcube";
        colcube.transform.localPosition = new Vector3(5, 0, 5);
        colcube.GetComponent<Renderer>().material.color = new Color(1, 0, 0, 0.7f);
        colcube.AddComponent<CastScript>();
        colcube.GetComponent<CastScript>().caller = castTrigger ;//

        //
        var mover = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        mover.name="player";
        mover.transform.localPosition = new Vector3(0,10,0);
        mover.GetComponent<Renderer>().material.color = new Color(0, 0, 1, 1);
        mover.AddComponent<player>();

        //
        var camera =Camera.main.gameObject;
        camera.transform.SetParent(mover.transform,false);
        camera.transform.localPosition=new Vector3(0,0,-0.3f);

    }
    void castTrigger(Collider other, GameObject go, string timing)
    {
        Debug.Log(other.gameObject.name);
        Debug.Log(timing + " : " + go.name);
    }

}//class











public class CastScript : MonoBehaviour
{
    [SerializeField] public string debug = "";

    //注意：instatntlateで複製した時には、callerは外れるため、再度設定する必要がある。
    public System.Action<Collider, GameObject, string> caller;
    void Awake()
    {
        var co = gameObject.GetComponent<MeshCollider>();
        if (co != null) co.convex = true;
        var co2 = gameObject.GetComponent<Collider>();
        co2.isTrigger = true;
        this.caller = _caller;
    }
    void _caller(Collider other, GameObject go, string timing)
    {
        Debug.Log("dummy:" + go.name + ":" + timing);
    }
    void OnTriggerEnter(Collider other) => caller(other, gameObject, "Enter");
    void OnTriggerStay(Collider other) {/*heavy*/}
    void OnTriggerExit(Collider other) => caller(other, gameObject, "Exit");
}//class




public class player : MonoBehaviour
{
    CharacterController ctr;
    void Start()
    {
#if !UNITY_WEBGL
        Application.targetFrameRate = 20;
#endif
        ctr = gameObject.GetComponent<CharacterController>();
        if (ctr == null)
        {
            gameObject.AddComponent<CharacterController>();
            ctr = gameObject.GetComponent<CharacterController>();
            ctr.height = 0.9f;
            ctr.skinWidth = ctr.height * 0.1f;
            ctr.radius = 0.4f;
            ctr.stepOffset = ctr.radius * 0.1f;
            ctr.minMoveDistance = 0.001f;
            ctr.slopeLimit = 45f;
        }
        //ctr = gameObject.GetComponent<CharacterController>();
    }
    void Update()
    {
        //カメラをこのオブジェクトの下に加えると追従。
        float speed = 10.0f / 2;
        float rotspeed = 360f / 1;
        float gravity = 9.8f;//落下が早すぎると接触をすり抜けることがある。
        float ty = ctr.isGrounded ? 0 : -1 * /*gravity **/ gravity * Time.deltaTime;
        float tz = ctr.isGrounded ? Input.GetAxis("Vertical") * speed * Time.deltaTime : 0;
        float ry = ctr.isGrounded ? Input.GetAxis("Horizontal") * rotspeed * Time.deltaTime : 0;

        //transform.Translate(0, 0, tz);
        ctr.Move(transform.TransformDirection(0, ty, tz));
        transform.Rotate(0, ry, 0);

        if (Input.GetKeyDown("space"))
        {
            transform.Round().RoundAngleY();
            //Debug.Log(ctr.isGrounded);
        }
    }
}//class

static class transformRoundExtension
{
    public static Transform Round(this Transform @this, bool yesX = true, bool yesY = false, bool yesZ = true)
    {
        var demi = 0.001f;//just 0.5 is upper;
        var p = @this.localPosition;
        var x = yesX ? Mathf.Round(p.x + demi) : p.x;
        var y = yesY ? Mathf.Round(p.y + demi) : p.y;
        var z = yesZ ? Mathf.Round(p.z + demi) : p.z;
        @this.localPosition = new Vector3(x, y, z);
        return @this;
    }
    public static Transform RoundAngleY(this Transform @this, float angle = 90)
    {
        var demi = angle / 2 + 0.001f;//just 0.5 is upper;
        var q = @this.localRotation.eulerAngles;
        var y = (int)(Mathf.Round(q.y + demi) / angle) * angle;
        @this.localRotation = Quaternion.Euler(q.x, y, q.z);
        return @this;
    }

}//class
```