Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Problems with product rotation script

Discussion in 'Scripting' started by AleaG, May 22, 2015.

  1. AleaG

    AleaG

    Joined:
    Oct 7, 2013
    Posts:
    2
    Hi,

    Having real problems at work with a script which is meant to pull a product in front of a camera, rotate the product a fixed number of degrees a fixed number of times and then drops the product.

    • It triggers when the camera (tagged "OnRailsCamera") hits a collider box which has the script attached.
    • A target locator gameobject is created in front of the camera and the product is moved to the target locator and rotated to match the camera rotation, gets parented to the target locator and then is rotated using quaternions and a simple timer.
    • Once the target number of rotations are reached the product is dropped and destroyed.
    At the moment it works fine in an empty scene (which I used to create the script). In our main scene it does some odd rotations (seemingly at random) before dropping. Not really sure what's going on and would really appreciate another pair of eyes going through and seeing what I'm missing/doing wrong (probably some stupid mistake/mistakes throughout).

    Thanks very much!

    Code (CSharp):
    1. public class ProductSelect : MonoBehaviour
    2. {
    3.     public    GameObject        _camera, _theProduct, _productTarget;
    4.  
    5.     // Vector3 position in front of camera for product to move to
    6.     public    Vector3            _inFrontCamera;
    7.    
    8. //    private    Vector3            _theProductStartRotation, _theProductStartPosition;
    9.  
    10.     public    List<Vector3>    _theProductRotationsLi;
    11.     public    Vector3            _fixedRotationAmount;
    12.     public    bool            _isFixedRotation;
    13.  
    14.     private    bool            _isAnimated;
    15.     private    bool            _isTimerStarted;
    16.  
    17.     // Set this to true if you want the user to click to continue once the product animations have finished
    18.     public    bool            _isClickFinish;
    19.  
    20.     // Set this to true if you want the scene to continue automatically once the product animations have finished
    21.     public    bool            _isAutomaticFinish;
    22.  
    23.     private    bool            _isCheckHeight;
    24.  
    25.     private    float            _startTime, _targetTime, _countTime;
    26.  
    27.     // Amount of time to pause between each product rotation
    28.     public    float            _pauseTime;
    29.  
    30.     // Speed of product rotation
    31.     public    float            _rotateSpeed;
    32.  
    33.     // Speed of product movement when moving into position in front of player
    34.     public    float            _moveSpeed;
    35.  
    36.     private    bool            _rotating;
    37.     private    float            _currAngle;
    38.  
    39.  
    40.     public    float            _speed;
    41.  
    42.     private    int                _numRotations;
    43.  
    44.     // Set this to be the number of rotations you want the product to complete before stopping
    45.     public    int                _targetRotations;
    46.  
    47.     // NOTE: Need to implement the possibility of dropping product when mouse is clicked
    48.  
    49.     void Awake()
    50.     {
    51. /*
    52.         // Get the starting rotation of the product (rounded to whole number)
    53.         _theProductStartRotation = new Vector3(Mathf.Round(_theProduct.transform.localEulerAngles.x),
    54.                                                Mathf.Round(_theProduct.transform.localEulerAngles.y),
    55.                                                Mathf.Round(_theProduct.transform.localEulerAngles.z));
    56.  
    57.         // Get the starting position of the product
    58.         _theProductStartPosition = _theProduct.transform.position;
    59. */
    60.  
    61.         // Timer not started at beginning
    62.         _isTimerStarted = false;
    63.  
    64.         _rotating = false;
    65.  
    66.         // If no countdown time has been set, make it "2"
    67.         if(_pauseTime == 0)
    68.         {
    69.             _pauseTime = 2;
    70.         }
    71.  
    72.         // If no rotation speed has been set, make it "2"
    73.         if(_rotateSpeed == 0)
    74.         {
    75.             _rotateSpeed = 2;
    76.         }
    77.  
    78.         // No rotations have occurred at the start
    79.         _numRotations = 0;
    80.  
    81.         // If the target rotations amount has not been set, make it "2"
    82.         if(_targetRotations == 0)
    83.         {
    84.             _targetRotations = 2;
    85.         }
    86.  
    87.         // If the user has not set the finish mode to be either "Click Finish" or "Automatic Finish" then
    88.         // output an error and set the mode to be "Automatic Finish"
    89.         if(_isClickFinish && _isAutomaticFinish || !_isClickFinish && !_isAutomaticFinish)
    90.         {
    91.             _isAutomaticFinish = true;
    92.             throw new ArgumentException("No continuation mode chosen: please choose either 'Click Finish' or 'Automatic Finish' in future. " +
    93.                                         Environment.NewLine +
    94.                                         "Setting to 'Automatic Finish'");
    95.         }
    96.     }
    97.  
    98.     void Update()
    99.     {
    100. /*
    101.         // If spacebar is pressed
    102.         if(Input.GetKeyDown(KeyCode.Space))
    103.         {
    104.             // Turn on animations
    105.             _isAnimated = true;
    106.         }
    107. */
    108.  
    109.         // If animations are one
    110.         if(_isAnimated)
    111.         {
    112.             // And timer is started
    113.             if(_isTimerStarted == true)
    114.             {
    115.                 // Countdown the time
    116.                 _countTime += Time.deltaTime;
    117.  
    118.                 // If count time > target time
    119.                 if(_countTime >= _targetTime)
    120.                 {
    121.                     //// This is where we trigger ////
    122.  
    123.                     // And the product is set to rotate to fixed degrees
    124.                     if(_isFixedRotation)
    125.                     {
    126.                         // Declare quaternion to hold target rotation
    127.                         Quaternion _targetRot = new Quaternion();
    128.  
    129.                         // Set the target rotation angles, which are the product current rotation - the target rotation amount
    130.                         _targetRot.eulerAngles = new Vector3(Mathf.Round((_camera.transform.rotation.eulerAngles.x - _theProduct.transform.localEulerAngles.x) - _fixedRotationAmount.x),
    131.                                                              Mathf.Round((_camera.transform.rotation.eulerAngles.y - _theProduct.transform.localEulerAngles.y) - _fixedRotationAmount.y),
    132.                                                              Mathf.Round((_camera.transform.rotation.eulerAngles.z - _theProduct.transform.localEulerAngles.z) - _fixedRotationAmount.z));
    133.  
    134. //                        _targetRot.eulerAngles = new Vector3(Mathf.Round(_camera.transform.localEulerAngles.x - _fixedRotationAmount.x),
    135. //                                                             Mathf.Round(_camera.transform.localEulerAngles.y - _fixedRotationAmount.y),
    136. //                                                             Mathf.Round(_camera.transform.localEulerAngles.z - _fixedRotationAmount.z));
    137.  
    138.                         // Start the fixed rotation coroutine
    139.                         StartCoroutine(CRRotateFixedDegrees(_theProduct, _targetRot));
    140.  
    141. //                        StartCoroutine(CRRotateFixedDegrees1(_theProduct, _fixedRotationAmount.y));
    142.                     }
    143.                     else
    144.                     {
    145. //                        RotateToDegrees(_theProduct, _theProductRotationsLi);
    146.                     }
    147.  
    148.                     ////-------------------------////
    149.  
    150.                     // Stop the timer and reset the variables
    151.                     _isTimerStarted = false;
    152.                     _startTime = 0;
    153.                     _targetTime = 0;
    154.                 }
    155.             }
    156.  
    157.             // If the timer is stopped
    158.             if(_isTimerStarted == false)
    159.             {
    160.                 // Go to the timer start method
    161.                 StartTimer();
    162.             }
    163.         }
    164.        
    165.         // If we've reached the target number of rotations then disable the animations and drop the product
    166.         if(_numRotations == _targetRotations)
    167.         {
    168. //            Debug.Log("Reached target rotations");
    169.  
    170.             // Set fixed rotations to be off and switch off animations
    171.             _isFixedRotation = false;
    172.             _isAnimated = false;
    173.            
    174.             // If the product requires a mouse click to continue
    175.             if(_isClickFinish)
    176.             {
    177.                 // Wait for mouse button 0 to be pressed before dropping the product
    178.                 if(Input.GetKey(KeyCode.Mouse0))
    179.                 {
    180.                     DropProduct(_theProduct);
    181.  
    182.                     // NOTE: Need to continue path here!!!!!!!!!!!!!!!!!!!!
    183.                 }
    184.             }
    185.  
    186.             // If the product will be dropped automatically then drop the product
    187.             // when the target rotations are reached
    188.             if(_isAutomaticFinish)
    189.             {
    190.                 DropProduct(_theProduct);
    191.  
    192.                 iTween.Resume();
    193.  
    194.                 // NOTE: Need to continue path here!!!!!!!!!!!!!!!!!!!!
    195.             }
    196.         }
    197.  
    198.         // If we're checking the height (because the product has been dropped)
    199.         if(_isCheckHeight)
    200.         {
    201.             // If the product is only 0.1 units above y(0)
    202.             if(_theProduct.transform.position.y <= 0.1)
    203.             {
    204.                 // Destroy the product gameobject and set it to null
    205.                 Destroy(_theProduct);
    206.                 _theProduct = null;
    207.  
    208.                 // Destroy the product target gameobject and set it to null
    209.                 Destroy(_productTarget);
    210.                 _productTarget = null;
    211.  
    212.                 // Stop checking the height of the product as it no longer exists
    213.                 _isCheckHeight = false;
    214.             }
    215.         }
    216.     }
    217.  
    218.     void OnTriggerEnter (Collider _collider)
    219.     {
    220.         // If an on rails camera or player camera enters the collider
    221.         if(_collider.CompareTag("OnRailsCamera") || _collider.transform.name == "Player")
    222.         {
    223.             if(_theProduct != null)
    224.             {
    225.                 // Assign that camera in this script
    226.                 _camera = _collider.gameObject;
    227.        
    228.                 iTween.Pause();
    229.  
    230.                 // As long as not product target already exists
    231.                 if(_productTarget == null)
    232.                 {
    233.                     // Create the product target gameobject and name it
    234.                     _productTarget = new GameObject("Product Target");
    235.                 }
    236.  
    237.                 // Set the product target position to be at the camera
    238.                 _productTarget.transform.position = _camera.transform.position;
    239.  
    240.                 // Set the product target parent to be the camera
    241.                 _productTarget.transform.SetParent(_camera.transform);
    242.                
    243.                 // Translate the product target the specified distance around the camera
    244.                 _productTarget.transform.Translate(_camera.transform.forward * _inFrontCamera.z, Space.Self);
    245.                 _productTarget.transform.Translate(Vector3.up * _inFrontCamera.y, Space.Self);
    246.  
    247.                 // Set the rotation of the product to match that of the camera so that it lines up perpendicular when rotating
    248.                 // despite the camera angle of approach/orientation
    249.                 _productTarget.transform.eulerAngles = _camera.transform.eulerAngles;
    250.  
    251.                 // consider directly setting the product target position using transform.position to avoid it moving around when entering the collision box
    252.  
    253.                 // Move the product to the product target
    254.                 StartCoroutine(CRMoveToCamera(_theProduct, _productTarget));
    255.                 StartCoroutine(CRRotateToCamera(_theProduct));
    256.                 SetParent(_theProduct, _productTarget);
    257.  
    258.  
    259.                 //-------------------------------------------------------------------------------------------------------------------------------------------------
    260.  
    261. //                _theProduct.transform.SetParent(_productTarget.transform);
    262.    
    263.                 // Move the product to be at the product target location, rotation and parent
    264. //                _theProduct.transform.position = _productTarget.transform.position;
    265. //                _theProduct.transform.rotation = _camera.transform.rotation;
    266. //                _theProduct.transform.SetParent(_productTarget.transform);
    267.  
    268.                 //----------------------------------------------------------------------------------------------------------------------------------------------
    269.  
    270.                 // If we're rotating the product fixed degree increments
    271.                 if(_isFixedRotation)
    272.                 {
    273.                     // Start the animation
    274.                     _isAnimated = true;
    275.                 }
    276.             }
    277.         }
    278.     }
    279.    
    280.     void StartTimer()
    281.     {
    282.         // If the timer is not started
    283.         if(_isTimerStarted == false)
    284.         {
    285.             // Get the start time
    286.             _startTime =        Time.time;
    287.             // Calculate the target time
    288.             _targetTime =        _startTime + _pauseTime;
    289.             // Set the count time
    290.             _countTime =        _startTime;
    291.             // Start the timer
    292.             _isTimerStarted =    true;
    293.         }
    294.     }
    295.  
    296.     IEnumerator CRMoveToCamera (GameObject _product, GameObject _target)
    297.     {
    298.         yield return new WaitForSeconds(1);
    299.  
    300.         // Create a target position vector3 for the product to move to
    301.         Vector3 _targetPosition        =    _target.transform.position;
    302.  
    303.         // While the player's position does not match the target position
    304.         while(_product.transform.position != _targetPosition)
    305.         {
    306.             // Calculate movement from the player co-ordinates to the target co-ordinates and move the product
    307.             _product.transform.position    =    Vector3.MoveTowards(_product.transform.position, _targetPosition, _moveSpeed * Time.deltaTime);
    308.            
    309.             // Remain in this loop until the current position matches the target position
    310.             yield return null;
    311.         }
    312.  
    313.         // Set the product rotation to match the camera rotation
    314. //        _product.transform.eulerAngles = _camera.transform.eulerAngles;
    315.     }
    316.  
    317.     IEnumerator CRRotateToCamera(GameObject _product)
    318.     {
    319.         // While the product's rotation does not match the camera's rotation
    320.         while(_product.transform.localEulerAngles != _camera.transform.localEulerAngles)
    321.         {
    322.             // Calculate the rotation to match the camera rotation and move the product
    323.             _product.transform.localEulerAngles = Vector3.MoveTowards(_product.transform.localEulerAngles, _camera.transform.localEulerAngles, _rotateSpeed);
    324.            
    325.             // Remain in this loop until the current position matches the target position
    326.             yield return null;
    327.         }
    328.     }
    329.  
    330.     void SetParent(GameObject _product, GameObject _target)
    331.     {
    332.         // Parent the product to the product target
    333.         _product.transform.SetParent(_target.transform);
    334.     }
    335.  
    336.     IEnumerator CRRotateFixedDegrees (GameObject _product, Quaternion _QRot)
    337.     {
    338.         // Store the current rotation of the product
    339.         Quaternion _currentRotation    =    _product.transform.rotation;
    340.  
    341.         // New rotation of the player (calculated lerp between player rotation and target rotation)
    342.         Quaternion _newRotation        =    Quaternion.identity;
    343.        
    344.         // Target rotation (passed in from camera locator)
    345.         Quaternion _targetRotation    =    _QRot;
    346.  
    347.         // Count the number of rotations that have occurred
    348.         _numRotations++;
    349.  
    350.         // Rotate the player until their rotation matches the target rotation
    351.         while(_currentRotation != _targetRotation)
    352.         {
    353.             // Get the rotation from the current rotation to the target rotation
    354. //            _newRotation = Quaternion.RotateTowards(_currentRotation, _camera.transform.rotation * _targetRotation, _rotateSpeed);
    355.             _newRotation = Quaternion.RotateTowards(_currentRotation, _targetRotation, _rotateSpeed);
    356.  
    357.             // Calculate the rotation of the player by lerping from the current rotation to the target rotation
    358. //            _newRotation = Quaternion.Lerp(_currentRotation, _targetRotation, _moveSpeed * Time.deltaTime);
    359.            
    360.             // Rotate the player towards the target rotation
    361.             _product.transform.rotation    =    _newRotation;
    362.            
    363.             // Update the current rotation to match the new rotation
    364.             _currentRotation            =    _newRotation;
    365.  
    366.             // Remain in this loop until the current position matches the target position
    367.             yield return null;
    368.         }
    369.     }
    370.  
    371.     IEnumerator CRRotateFixedDegrees1 (GameObject _product, float _angle)
    372.     {
    373.         if (_rotating)
    374.         {
    375.             // Ignore calls to RotateAngle while _rotating
    376. //            return;
    377.         }
    378.  
    379.         Vector3 _curEuler = _product.transform.eulerAngles;
    380.  
    381.         // Start rotating
    382.         _rotating = true;
    383.  
    384.         // Calculate the new angle
    385.         Vector3 _newAngle = new Vector3(_curEuler.x, _curEuler.y + _angle, _curEuler.z);
    386.  
    387.         // While the current angle does not match the new angle
    388.         while (_curEuler != _newAngle)
    389.         {
    390.             // Move towards the new angle at a constant _speed
    391.             _curEuler.y = Mathf.MoveTowards(_curEuler.y, _newAngle.y, _speed * Time.deltaTime);
    392.  
    393.             // Update the object's rotation...
    394.             _product.transform.eulerAngles = _curEuler;
    395.        
    396.             yield return null;
    397.         }
    398.  
    399.         // Stop rotating
    400.         _rotating = false;
    401.     }
    402.  
    403.     void DropProduct (GameObject _product)
    404.     {
    405.         // Unparent the product
    406.         _product.transform.SetParent(null);
    407.  
    408.         // Enable the box collider on the product
    409.         _product.GetComponent<BoxCollider>().enabled = true;
    410.  
    411.         // Enable the rigidbody on the product
    412.         _product.GetComponent<Rigidbody>().useGravity = true;
    413.  
    414.         // Move the product towards the camera as if the viewer is taking it
    415.         _product.GetComponent<Rigidbody>().AddForce(_camera.transform.forward * -10f);
    416.  
    417.         // Start checking the product height above 0 on y
    418.         _isCheckHeight = true;
    419.  
    420.         // Reset the number of product rotations to 0
    421.         _numRotations = 0;
    422.     }
    423. }