I’ve been trying to convert this script from Clive Jackson over at Blink3D
to Unity3D and I’m completely at sea (with no lifejacket and the waters freezing)
… so any help would be greatly appreciated.
The script produces a working clock in Blink with three hands
(hours.minutes,seconds)
In Unity i can’t even get it to pass the time in real time to the GUIText, and as for rotation - well i can get stuff to rotate with the Transform.Rotate class but how do I get from that to something locked to the system clock ?:
this is where i’ve got to and failed so far:
import System;
var displayTime : GUIText;
var date = DateTime.Now.ToString("hh:mm:ss");
function FixedUpdate()
{
var curDate;
transform.Rotate((60-curDate.getSeconds()) / 60) *(2*Pi);
}
but i run into endless errors (ie. all my fixes as i work backward amount to nothing !
For a start I can’t work out how to Define Math.Pi but there’s other stuff in there that i’m obviously also don’t understand.
import System;
var timeDisplay : GUIText;
var handBase : Transform;
function Update () {
var timeNow : DateTime = DateTime.Now;
timeDisplay.text = timeNow.Second.ToString();
RotateSecondsHand(timeNow.Second);
}
function RotateSecondsHand(seconds : int)
{
handBase.eulerAngles = Vector3(0,0,0);
// x6.0 since each second will go through 6 degrees
// x -1.0 so will rotate counter clockwise around z-axis.
handBase.Rotate(0.0, 0.0, seconds * 6.0 * -1.0); // x -1.0 so rotates clockwise around z-zxis
}
I have attached a package that has the second hand as a GameObject. As of now, I do not think you can rotate GUITextures or GUIText. You can add hours and minutes hands by following the same process as is done for the second hand. Note in the project I have the second hand as a capsule as a child of a sphere that is set to not display. I did that because I could not get it to work correctly when it was a child of an empty game object.
Superb !
Thanks very much, that works exactly as billed.
Additional note:
For the hour hand to be correctly positionned at the minute positions
of 0, 5, 10, 15, 20. 25. 30 etc. the seconds just need to be multiplied by 30 degrees rather than 6:
Michael, You will need to add 2 new methods for rotating a minute and hour hand. Doing this is really no more than a copy paste of the template that was posted for the seconds. Although the code to rotate all 3 hands could be done in 3 lines of code contained in the update. Reading about the EulerAngels method should put you in good stead
You will obviously need a reference to the transforms that represent the hands.
Take a look at the DateTime.Now in the MSDN documentation and you will see it has properties for Seconds, Minutes and Hours - just pass the respective element to the functions you have created in the update (Just like for the seconds).
The method for rotating the minute is the same as the second, Just change the name’s to match and for the hours Louis explains you need to change the grain from (360 / 60) = 6 to (360 / 12) = 30 . He just neglected to update the name of the variable…
Give it a try and come back if you have any specific questions.
Rather than having seperate GUItext components for each element of the time. Why not have a single time GUIText and set it’s text property to the result of a formatted date. .NET is able to format the date to however you want it to appear… Take a look in the MSDN Library at this document describing Standard Date and Time Format String. If there isn’t a format there you can create your own custom formatter
var digitalTime : GUIText;
function Update () {
var timeNow : DateTime = DateTime.Now;
//Set the text property of digitialTime GUI element to a Long Time Format (Eg: 2:22:48 PM )
digitalTime.text = timeNow.ToString("T");
[snip]
if you do want to keep your elements seperate try replacing timeSecond.text = timeNow.Second.ToString(); with timeSecond.text = timeNow.ToString(“ss”);
You an change the colour of the text by accessing the material.color property
// Change the material to display green text.
guiText.material.color = Color.green;
The code you’ve got is good although I can see a couple of issue:
you are referencing the same transform ‘handBase’ in each of your methods. I would expect you to need 3 (SecondHandBase, MinuteHandBase HourHandBase) that get rotated in the respective method calls.
there are 60 minutes in the hour, so you’ll need to * by 6 as you do with the seconds when computing the rotation to apply for the minutes.
import System;
var digitalTime : GUIText;
var hourHandBase : Transform;
var minuteHandBase : Transform;
var secondHandBase : Transform;
function Update () {
// Record the current DateTime
var timeNow : DateTime = DateTime.Now;
// Set the digital time text to a format pattern
Debug.Log (timeNow.ToString("hh:mm:ss"));
digitalTime.text = timeNow.ToString("hh:mm:ss");
// Rotate the hands of our analogue clock, Note timeNow.Hour returns a 24
// hour value hence the need to format using the 12 hour 'h' format symbol.
hourHandBase.eulerAngles = Vector3(0,0,int.Parse(timeNow.ToString("%h")) * 30 * -1 );
minuteHandBase.eulerAngles = Vector3(0,0,timeNow.Minute * 6.0 * -1 );
secondHandBase.eulerAngles = Vector3(0,0,timeNow.Second * 6.0 * -1 );
}
The reason you are getting that message is because Format is a method of DateTime not int,
so instead you’ll need to remove the .Hour leaving you with timeNow.ToString(“%h”)
btw, the code I supplied has been untested as I’m not at a machine with unity on. you may need to explicitly convert the format result to an int if there is a problem.
Michael, I’ve tested and updated the code I posted earlier. This works for all 3 hands as well as formatting the time for the GUIText
You will need to apply this script to a root gameobject that has a hierarchy of bases for each hand. each base contains a mesh (or cube) that you offset so the pivot point of the base is at the end of the mesh. You then drag each of the bases on to the corresponding element in the inspector on the root… Hope this makes sense.