I am quite new to game engine programming, coming from the animation/modelling end of the field. I recently found out about Unity, and realised this application is a great tool to finally get into interactive 3D. I have gone through a fair number of tutorials, and purchased a licence for Unity Pro.
What I am trying to put together at the moment has turned out to be not entirely straightforward, so I need some advice.
Imagine for example a car model that you can spin around in space by dragging over it with the mouse. The model will have hotspots that you can interact with: for example if you click on the bonnet, an animation is triggered that opens it up, and overlayered pop-up information appears. How would I go about doing this?
I found this “grabNRotate” java script by DannyJ in the Unity Web forum that took care of the spinning function (Thanks Danny!).
var numberAverages : int = 3;
private var originalRotation : Quaternion;
private var offsetRotation : Quaternion;
// Make sure there is always a Rigidbody
@script RequireComponent (Rigidbody)
@script RequireComponent (SphereCollider)
function Awake () {
numberAverages = Mathf.Clamp (numberAverages, 1, numberAverages);
}
function OnMouseDown () {
var hit : RaycastHit;
var dir : Vector3;
// Stop spinning
rigidbody.angularVelocity = Vector3.zero;
// Record initial variables
if (Physics.Raycast (camera.main.ScreenPointToRay(Input.mousePosition), hit)) {
originalRotation = transform.rotation;
dir = hit.point - transform.position;
offsetRotation = Quaternion.Inverse (Quaternion.LookRotation (dir));
Spin (dir);
}
}
function Spin (dir : Vector3) {
var hit : RaycastHit;
var previousDirList : Array = new Array ();
var currentDir : Vector3;
// Initialize previous dir list
for (var i : int = 0; i < numberAverages; i++) {
previousDirList.Add (currentDir);
}
currentDir = dir;
// Make the object rotate with the cursor while we are grabbing it
while (Input.GetButton ("Fire1") Physics.Raycast (camera.main.ScreenPointToRay(Input.mousePosition), hit)) {
// Remove first element of the array
previousDirList.RemoveAt (0);
// Add current dir to the end
previousDirList.Add (currentDir);
currentDir = hit.point - transform.position;
transform.rotation = Quaternion.LookRotation (currentDir) * offsetRotation * originalRotation;
yield;
}
// User let go of the mouse so make the object spin on its own
var avgPreviousDir : Vector3 = Vector3.zero;
for (dir in previousDirList) {
avgPreviousDir += dir;
}
avgPreviousDir /= numberAverages;
Kick (currentDir, avgPreviousDir);
}
function Kick (r2 : Vector3, r1 : Vector3) {
var linearVelocity : Vector3;
var angVelocity : Vector3;
// Calculate the angular velocity: omega = r x v / r^2
linearVelocity = (r2 - r1) / Time.deltaTime;
rigidbody.angularVelocity = Vector3.Cross (r2, linearVelocity) / r2.sqrMagnitude;
}
To achieve the hotspot funcionality I have tried adding child objects (cubes) with simple test scripts attached to them (for example switching a colour on mouseDown), but they become inactive when parented to the main object (the sphere), and furthermore they inherit the grabNRotate behavior instead.
Another couple of problems I have encountered with the grabNRotate script:
-
When I build a Windows standalone, it works differently on different computers. On some, the object goes on spinning on its own (as it should) when you drag off the object/let go of the mouse, on others the object will only rotate with the mouse drag movement and stops when you let go. My guess is that that this is java script related, but I haven’t been able to find any setting that rectifies it.
I should mention that the functionality is fine when I test it in the editor. -
I have also tried using a mesh collider instead of the sphere collider, but this results in occasional rapid shivering/vibrating movements of the object when you drag.
I know, I am very much a programming newbie, so please bear with me. Maybe there are some basic bits that I have missed.
Any suggestions/hints/pointers in the right direction would be really appreciated!
Cheers,
Mats Bjorklund,
Melbourne, Australia