Guest User

Untitled

a guest
Apr 20th, 2016
300
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.47 KB | None | 0 0
  1. using UnityEngine;
  2.  
  3. [RequireComponent(typeof(Collider))]
  4. public class SnappingUnits : MonoBehaviour {
  5.  
  6.     ///<summary>the grid we want to snap to </summary>
  7.     public GFGrid _grid;
  8.     ///<summary> A collider attached to the grid, will be used for handling mouse input. </summary>
  9.     private Collider gridCollider;
  10.    
  11.     ///<summary> True while the player is dragging the block around, otherwise false. </summary>
  12.     private bool beingDragged;
  13.     ///<summary>  The previous valid position. </summary>
  14.     private Vector3 oldPosition;
  15.  
  16.     void Awake () {
  17.         _grid = GameObject.Find("Rectangular Grid").GetComponent<GFRectGrid>();
  18.         gridCollider = _grid.gameObject.GetComponent<Collider> ();
  19.         //perform an initial align and snap the objects to the bottom
  20.         _grid.AlignTransform (transform);
  21.         transform.position = CalculateOffsetY ();
  22.         //store the first safe position
  23.         oldPosition = transform.position;
  24.         // setup the rigidbody for collision and contstruct a trigger
  25.         SetupRigidbody();
  26.         ConstructTrigger();
  27.     }
  28.    
  29.     // these two methods toggle dragging
  30.     void OnMouseDown(){
  31.         beingDragged = true;
  32.     }
  33.     void OnMouseUp(){
  34.         beingDragged = false;
  35.         transform.position = oldPosition; // place on the last valid position
  36.         _intersecting = 0; // stationary block do not intersect anymore
  37.         TintRed(_intersecting); // set the tint one last time
  38.     }
  39.    
  40.     // use FixedUpdate instead of Update to allow colision detection to catch up with movement
  41.     void FixedUpdate(){
  42.         if(beingDragged){
  43.             //store the position if it is valid
  44.             if(_intersecting == 0)
  45.                 oldPosition = transform.position;
  46.             DragObject();
  47.         }
  48.     }
  49.    
  50.     //this function gets called every frame while the object (its collider) is being dragged with the mouse
  51.     void DragObject(){
  52.         if(!_grid || !gridCollider) // if there is no grid or no collider there is nothing more we can do
  53.             return;
  54.  
  55.         //handle mouse input to convert it to world coordinates
  56.         var cursorWorldPoint = ShootRay();
  57.        
  58.         //change the X and Z coordinates according to the cursor (the Y coordinate stays the same after the last step)
  59.         transform.position = cursorWorldPoint;
  60.        
  61.         //now align the object and snap it to the bottom.
  62.         _grid.AlignTransform(transform);
  63.         transform.position = CalculateOffsetY(); // this forces the Y-coordinate into position
  64.     }
  65.    
  66.     // makes the object snap to the bottom of the grid, respecting the grid's rotation
  67.     Vector3 CalculateOffsetY(){
  68.         //first store the objects position in grid coordinates
  69.         var gridPosition = _grid.WorldToGrid(transform.position);
  70.         //then change only the Y coordinate
  71.         gridPosition.y = 0.5f * transform.lossyScale.y;
  72.        
  73.         //convert the result back to world coordinates
  74.         return _grid.GridToWorld(gridPosition);
  75.     }
  76.  
  77.     // shoots a ray, which can only hit the grid plane, from the mouse cursor via the camera and returns the hit position
  78.     Vector3 ShootRay () {
  79.         RaycastHit hit;
  80.         gridCollider.Raycast (Camera.main.ScreenPointToRay (Input.mousePosition), out hit, Mathf.Infinity);
  81.         //this is where the player's cursor is pointing towards (if nothing was hit return the current position => no movement)
  82.         return hit.collider != null ? hit.point : transform.position;
  83.     }
  84.  
  85.  
  86. //= The following is just for the red tint when intersecting, it has nothing to do with snapping ===============
  87.  
  88.     #region Intersection handling
  89.     public Material _defaultMaterial;
  90.     public Material _redMaterial;
  91.     //this keeps track of how many other cubes we are intersecting with
  92.     private int _intersecting;
  93.  
  94.     // this method will be called by the trigger
  95.     public void SetIntersecting(bool intersecting){
  96.         if(!beingDragged) // ignore sitting objects, only moving ones should respond
  97.             return;
  98.         // if true we entered another object, increment the value; if false we exited another object, decrease the value
  99.         _intersecting = intersecting ? _intersecting + 1 : _intersecting - 1;
  100.         //update the colour
  101.         TintRed(_intersecting);
  102.     }
  103.  
  104.     void TintRed(int intersections){
  105.         gameObject.GetComponent<Renderer>().material = intersections > 0 ? _redMaterial : _defaultMaterial;
  106.     }
  107.  
  108.     // set up the rigidbody component for intersection recognition
  109.     private void SetupRigidbody(){
  110.         Rigidbody rb = GetComponent<Rigidbody>(); //the rigidbody component of this object
  111.         if(!rb) // if there is no Rigidbody yet create a new one
  112.             rb = gameObject.AddComponent<Rigidbody>();
  113.         // non-kinematic to allow collision detection, no gravity and all rotations and movement frozen
  114.         rb.isKinematic=false;
  115.         rb.useGravity=false;
  116.         rb.constraints = RigidbodyConstraints.FreezeAll; //prevents physics from moving the object
  117.     }
  118.  
  119.     // create a child GameObject and add a trigger to it to do the intersection detection
  120.     private void ConstructTrigger(){
  121.         var go = new GameObject();
  122.         go.name = "IntersectionTrigger";
  123.         // attach it to this block and make it exactly the same, except slightly smaller
  124.         go.transform.parent = transform;
  125.         go.transform.localPosition = Vector3.zero; //exactly at the centre of the actual object
  126.         go.transform.localScale = 0.9f * Vector3.one; //slightly smaller than the actual object
  127.         go.transform.localRotation = Quaternion.identity; // same rotation as the actual object
  128.         // add the same type of collider as the block has and make it a trigger
  129.         var col = (Collider) go.AddComponent(GetComponent<Collider>().GetType());
  130.         col.isTrigger = true;
  131.         // attach the script to the collider and connect it to this script
  132.         IntersectionTrigger script = go.AddComponent<IntersectionTrigger>();
  133.         script.SetSnappingScript(this);
  134.     }
  135.     #endregion
  136. }
Add Comment
Please, Sign In to add comment