Simple Clock

확인 완료한 버전: 4

-

난이도: 초급

In this tutorial we'll write a small C# script to animate the arms of a very simple clock.

In this tutorial we will learn to:

  • create an object hierarchy;
  • create a script and attach it to an object;
  • access namespaces;
  • use the Update method;
  • rotate stuff based on time.

We assumed that you already have a basic understanding of Unity's editor. If you've played with it for a few minutes you're good to go.

Alt Clock 01

Creating the clock

We start by creating a new Unity project without any packages. The default scene contains a camera positioned at (0, 1, -10) looking down the Z axis. To get a similar perspective as the camera in the scene view, select the camera and perform GameObject / Align View to Selected from the menu. We need an object structure to represent the clock.

  • Create a new empty GameObject via GameObject / Create Empty, set its position to (0, 0, 0), and name it Clock.
  • Create three empty child objects for it and name them Hours, Minutes, and Seconds. Make sure they are all positioned at (0, 0, 0) as well.
  • We'll use simple boxes to visualize the arms of the clock. Create a child cube for each arm via GameObject / Create Other / Cube.
  • Give the cube for Hours position (0, 1, 0) and scale (0.5, 2, 0.5).
  • For the minutes cube it's position (0, 1.5, 0) and scale (0.25, 3, 0.25).
  • For seconds cube it's (0, 2, 0) and (0.1, 4, 0.1).

Alt Clock 02

Animating the clock

We need a script to animate the clock.

  • Create a new C# script via Create / C# Script in the Project view and name it ClockAnimator.
  • Open the script and empty it so we can start fresh.
  • First, we indicate that we want to use stuff from the UnityEngine namespace.
  • Then we declare the existence of the ClockAnimator. We describe it as a publicly available class that inherits from MonoBehaviour.
  • This gives us a minimal class that can be used to create components. Save it, then attach it to the the Clock object by dragging from the Project view to the Hierarchy view, or via the Add Component button.

Code snippet

using UnityEngine;

public class ClockAnimator : MonoBehaviour {
}

Alt Clock 03

To animate the arms, we need access to their Transform components first. Add a public Transform variable for each arm to the script, then save it. These public variables will become component properties which you can assign object to in the editor. The editor will then grab the Transform components of these objects and assign them to our variables. Select the Clock object, then drag the corresponding objects to the new properties.

Code snippet

using UnityEngine;

public class ClockAnimator : MonoBehaviour {

    public Transform hours, minutes, seconds;
}

Alt Clock 04a Alt Clock 04b

Next, we'll add an update method to the script. This is a special method that will be called once every frame. We'll use it to set the rotation of the clock arms. After saving the script, the editor will notice that our component has an update method and will show a checkbox that allows us to disable it. Of course we keep it enabled.

Code snippet

using UnityEngine;

public class ClockAnimator : MonoBehaviour {

    public Transform hours, minutes, seconds;

    void Update () {
        // currently do nothing
    }
}

Alt Clock 05

Each hour, the Hours arm has to rotate 360/12 degrees. The Minutes arm has to rotate 360/60 degrees per minute. Finally, the Seconds arm has to rotate 360/60 degrees every second. Let's define these values as private constant floating-point values for convenience.

Code snippet

using UnityEngine;

public class ClockAnimator : MonoBehaviour {

    private const float
        hoursToDegrees = 360f / 12f,
        minutesToDegrees = 360f / 60f,
        secondsToDegrees = 360f / 60f;

    public Transform hours, minutes, seconds;

    void Update () {
        // currently do nothing
    }
}

Each update we need to know the current time to get this thing to work. The System namespace contains the DateTime struct, which is suited for this job. It has a static property named Now that always contains the current time. Each update we need to grab it and store it in a temporary variable.

Code snippet

using UnityEngine;
using System;

public class ClockAnimator : MonoBehaviour {

    private const float
        hoursToDegrees = 360f / 12f,
        minutesToDegrees = 360f / 60f,
        secondsToDegrees = 360f / 60f;

    public Transform hours, minutes, seconds;

    void Update () {
        DateTime time = DateTime.Now;
    }
}

To get the arms to rotate, we need to change their local rotation. We do this by directly setting the localRotation of the arms, using quaternions. Quaternion has a nice method we can use to define an arbitrary rotation. Because we're looking down the Z axis and Unity uses a left-handed coordinate system, the rotation must be negative around the Z axis.

Code snippet

using UnityEngine;
using System;

public class ClockAnimator : MonoBehaviour {

    private const float
        hoursToDegrees = 360f / 12f,
        minutesToDegrees = 360f / 60f,
        secondsToDegrees = 360f / 60f;

    public Transform hours, minutes, seconds;

    void Update () {
        DateTime time = DateTime.Now;
        hours.localRotation = Quaternion.Euler(0f, 0f, time.Hour * -hoursToDegrees);
        minutes.localRotation = Quaternion.Euler(0f, 0f, time.Minute * -minutesToDegrees);
        seconds.localRotation = Quaternion.Euler(0f, 0f, time.Second * -secondsToDegrees);
    }
}

Alt Clock 06

Improving the clock

This works! When in play mode, our clock shows the current time. However, it behaves much like a digital clock as it only shows discrete steps. Let's include an option to show analog time as well. Add a public boolean variable analog to the script and use it to determine what to do in the update method. We can toggle this value in the editor, even when in play mode.

Code snippet

using UnityEngine;
using System;

public class ClockAnimator : MonoBehaviour {

    private const float
        hoursToDegrees = 360f / 12f,
        minutesToDegrees = 360f / 60f,
        secondsToDegrees = 360f / 60f;

    public Transform hours, minutes, seconds;

    public bool analog;

    void Update () {
        if (analog) {
            // currently do nothing
        }
        else {
            DateTime time = DateTime.Now;
            hours.localRotation = Quaternion.Euler(0f, 0f, time.Hour * -hoursToDegrees);
            minutes.localRotation = Quaternion.Euler(0f, 0f, time.Minute * -minutesToDegrees);
            seconds.localRotation = Quaternion.Euler(0f, 0f, time.Second * -secondsToDegrees);
        }
    }
}

Alt Clock 07

For the analog option we need a slightly different approach. Instead of DateTime.Now we'll use DateTime.Now.TimeOfDay, which is a TimeSpan. This allows us easy access to the fractional elapsed hours, minutes, and seconds. Because these values are provided as doubles – double precision floating-point values – we need to cast them to floats.

Code snippet

using UnityEngine;
using System;

public class ClockAnimator : MonoBehaviour {

    private const float
        hoursToDegrees = 360f / 12f,
        minutesToDegrees = 360f / 60f,
        secondsToDegrees = 360f / 60f;

    public Transform hours, minutes, seconds;
    public bool analog;

    void Update () {
        if (analog) {
            TimeSpan timespan = DateTime.Now.TimeOfDay;
            hours.localRotation =
                Quaternion.Euler(0f,0f,(float)timespan.TotalHours * -hoursToDegrees);
            minutes.localRotation =
                Quaternion.Euler(0f,0f,(float)timespan.TotalMinutes * -minutesToDegrees);
            seconds.localRotation =
                Quaternion.Euler(0f,0f,(float)timespan.TotalSeconds * -secondsToDegrees);
        }
        else {
            DateTime time = DateTime.Now;
            hours.localRotation = Quaternion.Euler(0f, 0f, time.Hour * -hoursToDegrees);
            minutes.localRotation = Quaternion.Euler(0f, 0f, time.Minute * -minutesToDegrees);
            seconds.localRotation = Quaternion.Euler(0f, 0f, time.Second * -secondsToDegrees);
        }
    }
}

Now our clock works analog too!

Alt Clock 08

Jasper Flick

커뮤니티 집필자

Jasper Flick runs his Catlike Coding business from Amsterdam, the Netherlands. He got a Master's degree in computer science and worked a bunch of years as a .NET developer in the financial world. He discovered Unity in 2008 and has been using it ever since. He has a few products on the Asset Store and also writes C# scripting tutorials.

Scripting

  1. Scripts as Behaviour Components
  2. Variables and Functions
  3. Conventions and Syntax
  4. C# vs JS syntax
  5. IF Statements
  6. Loops
  7. Scope and Access Modifiers
  8. Awake and Start
  9. Update and FixedUpdate
  10. Vector Maths
  11. Enabling and Disabling Components
  12. Activating GameObjects
  13. Translate and Rotate
  14. Look At
  15. Linear Interpolation
  16. Destroy
  17. GetButton and GetKey
  18. GetAxis
  19. OnMouseDown
  20. GetComponent
  21. Delta Time
  22. Data Types
  23. Classes
  24. Instantiate
  25. Arrays
  26. Invoke
  27. Enumerations
  28. Switch Statements
  1. Properties
  2. Ternary Operator
  3. Statics
  4. Method Overloading
  5. Generics
  6. Inheritance
  7. Polymorphism
  8. Member Hiding
  9. Overriding
  10. Interfaces
  11. Extension Methods
  12. Namespaces
  13. Lists and Dictionaries
  14. Coroutines
  15. Quaternions
  16. Delegates
  17. Attributes
  18. Events
  1. Introduction to ECS
  2. Introduction to the Entity Component System and C# Job System
  3. ECS Overview
  4. Implementing Job System
  5. Implementing ECS
  6. Using the Burst Compiler
  1. Building a Custom Inspector
  2. The DrawDefaultInspector Function
  3. Adding Buttons to a Custom Inspector
  4. Unity Editor Extensions – Menu Items
  5. An Introduction to Editor Scripting
  6. Creating a Spline Tool
  7. Getting Started with IK
  1. Simple Clock
  2. MonoDevelop's Debugger
  3. Unity Editor Extensions – Menu Items
  4. Creating Meshes
  1. Mastering Unity Project Folder Structure - Version Control Systems
  1. Installation and Setup of Visual Studio
  2. Editing Your Game Code with Visual Studio
  3. Debugging Unity games in Visual Studio
  1. Scripting Primer and Q&A
  2. Scripting Primer and Q&A - Continued
  3. Scripting Primer and Q&A - Continued (Again)
  4. Persistence - Saving and Loading Data
  5. Object Pooling
  6. Introduction to Scriptable Objects
  7. How to communicate between Scripts and GameObjects
  8. Coding in Unity for the Absolute Beginner
  9. Sound Effects & Scripting
  10. Editor Scripting Intro
  11. Writing Plugins
  12. Property Drawers & Custom Inspectors
  13. Events: Creating a simple messaging system
  14. Ability System with Scriptable Objects
  15. Character Select System with Scriptable Objects
  16. Creating Basic Editor Tools
  1. Intro and Setup
  2. Data Classes
  3. Menu Screen
  4. Game UI
  5. Answer Button
  6. Displaying Questions
  7. Click To Answer
  8. Ending The Game and Q&A
  1. Intro To Part Two
  2. High Score with PlayerPrefs
  3. Serialization and Game Data
  4. Loading Game Data via JSON
  5. Loading and Saving via Editor Script
  6. Game Data Editor GUI
  7. Question and Answer
  1. Overview and Goals
  2. Localization Data
  3. Dictionary, JSON and Streaming Assets
  4. Localization Manager
  5. Startup Manager
  6. Localized Text Component
  7. Localized Text Editor Script
  8. Localization Q&A
  1. Introduction and Session Goals
  2. Particle Launcher
  3. Particle Collisions
  4. ParticleLauncher Script
  5. Particle Collisions and Scripting
  6. Random Particle Colors
  7. Drawing Decals with Particles
  8. Collecting Particle Information For Display
  9. Displaying Particles Via Script
  10. Droplet Decals
  11. Questions and Answers
  1. Introduction and Goals
  2. Project Architecture Overview
  3. Creating Rooms
  4. Creating Exits
  5. Text Input
  6. Reacting To String Input
  7. Input Actions And The Delegate Pattern
  8. Questions and Answers
  1. Introduction and Goals
  2. Project Architecture and Review
  3. Displaying Item Descriptions
  4. Examining Items
  5. Taking Items
  6. Displaying Inventory
  7. Action Responses
  8. Preparing The Use Item Dictionary
  9. Creating The Use Action
  10. Questions and Answers