IEnumerator TransformSelected(TransformType type) { isTransforming = true; totalScaleAmount = 0; totalRotationAmount = Quaternion.identity; Vector3 originalTargetPosition = _target.position; Vector3 planeNormal = (transform.position - _target.position).normalized; Vector3 axis = GetSelectedAxisDirection(); Vector3 projectedAxis = Vector3.ProjectOnPlane(axis, planeNormal).normalized; Vector3 previousMousePosition = Vector3.zero; while (!Input.GetMouseButtonUp(0)) { Ray mouseRay = MyCamera.ScreenPointToRay(Input.mousePosition); Vector3 mousePosition = Geometry.LinePlaneIntersect(mouseRay.origin, mouseRay.direction, originalTargetPosition, planeNormal); if (previousMousePosition != Vector3.zero && mousePosition != Vector3.zero) { if (type == TransformType.Move) { float moveAmount = ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projectedAxis) * moveSpeedMultiplier; _target.Translate(axis * moveAmount, Space.World); } if (type == TransformType.Scale) { Vector3 projected = (selectedAxis == Axis.Any) ? transform.right : projectedAxis; float scaleAmount = ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projected) * scaleSpeedMultiplier; //WARNING - There is a bug in unity 5.4 and 5.5 that causes InverseTransformDirection to be affected by scale which will break negative scaling. Not tested, but updating to 5.4.2 should fix it - https://issuetracker.unity3d.com/issues/transformdirection-and-inversetransformdirection-operations-are-affected-by-scale Vector3 localAxis = (space == TransformSpace.Local && selectedAxis != Axis.Any) ? _target.InverseTransformDirection(axis) : axis; if (selectedAxis == Axis.Any) { _target.localScale += (ExtVector3.Abs(_target.localScale.normalized) * scaleAmount); } else { _target.localScale += (localAxis * scaleAmount); } totalScaleAmount += scaleAmount; } if (type == TransformType.Rotate) { if (selectedAxis == Axis.Any) { Vector3 rotation = transform.TransformDirection(new Vector3(Input.GetAxis("Mouse Y"), -Input.GetAxis("Mouse X"), 0)); _target.Rotate(rotation * allRotateSpeedMultiplier, Space.World); totalRotationAmount *= Quaternion.Euler(rotation * allRotateSpeedMultiplier); } else { Vector3 projected = (selectedAxis == Axis.Any || ExtVector3.IsParallel(axis, planeNormal)) ? planeNormal : Vector3.Cross(axis, planeNormal); float rotateAmount = (ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projected) * rotateSpeedMultiplier) / GetDistanceMultiplier(); _target.Rotate(axis, rotateAmount, Space.World); totalRotationAmount *= Quaternion.Euler(axis * rotateAmount); } } NotifyTransformChanged(); } previousMousePosition = mousePosition; yield return(null); } totalRotationAmount = Quaternion.identity; totalScaleAmount = 0; isTransforming = false; }