オブジェクトを置く位置を制限する
平面から外れた位置でマウスボタンを放すと平面から離れる直前の位置に戻す。
https://dl.dropbox.com/u/67579260/Unity/Flick02/Flick02.html
using UnityEngine; using System.Collections; public class cMain : MonoBehaviour { // Use this for initialization void Start () { StartCoroutine(Flick()); } // Update is called once per frame void Update () { } /** * @brief 無限ループ. */ IEnumerator Flick() { Vector3 LiftUp = 1.0f*Vector3.zero; Vector3 LastOnPlane = Vector3.zero; while(true) { GameObject target = null; bool isEnd = false; while(!isEnd) { if(Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; int layer = 1<<LayerMask.NameToLayer("Flick"); if(Physics.Raycast(ray, out hit, Mathf.Infinity, layer)) { target = hit.collider.gameObject; if(target != null) { isEnd = true; target.renderer.material.color = Color.red; target.transform.position += LiftUp; } } } yield return 0; } bool isOnField = false; while(Input.GetMouseButton(0)) { yield return 0; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); Vector3 planeNormal = Vector3.up; float planeDistance = 0.0f; Vector3 p = IntersectRayPlane(ray, planeNormal, planeDistance) + LiftUp; target.transform.position = p; isOnField = UpdateLastOnPlane(ref LastOnPlane, p); } target.renderer.material.color = Color.white; target.transform.position -= LiftUp; if(!isOnField) { target.transform.position = LastOnPlane; } } } /** * @brief 直線と平面の交点. */ Vector3 IntersectRayPlane(Ray ray, Vector3 planeN, float planeD) { float t = -planeD-Vector3.Dot(planeN, ray.origin)/Vector3.Dot(planeN, ray.direction); return ray.origin + t * ray.direction; } /** * @brief 平面上を離れる直前を捉える. */ bool UpdateLastOnPlane(ref Vector3 save, Vector3 pos) { Ray ray = new Ray(pos+10.0f*Vector3.up, -Vector3.up); RaycastHit hit; int layer = 1<<LayerMask.NameToLayer("Field"); if(Physics.Raycast(ray, out hit, Mathf.Infinity, layer)) { GameObject obj = hit.collider.gameObject; if(obj != null) { save = hit.point; return true; } } return false; } }