电脑罗盘时钟代码_Unity实战之制作时钟

4eff9dc0785e40ff35868fe1a06c3596.png

程序员那些事

一同事最近bug特别多,假装关切问他有多少个bug,他回答:10。过几日,再问,

他回答:10。我:“这么多天过去了,怎么一点变化都没有?”,他:”哪里没有

变化啊,以前是十进制,现在变成十六进制。

大体步骤

1.在Hierarchy面板中创建一个对象

2.写一个脚本,将它附加到一个对象上

3.访问命名空间

4.通过方法更新对象数据

5.基于时间旋转物体

在这篇文章中,你将学到很多C#基础的知识,和一个有用的API。

在这篇文章中,我们将会写一个小的C#脚本,用于制作一个简单的时钟的动画。

假设你对Unity的编辑器有了一些基础的了解。如果你用Unity玩几分钟,也许你就大体上了解了。

f8db283b696f57b9457c082e949dfde4.png

最终效果如图

创建时钟

让我们创建一个新的工程。默认的场景中包含一个position为(0,1,-10)的相机。在相机视口中可以看到场景的一部分,选择这个相机,然后选择菜单中的 GameObject / AlignView便能获得你想看到场景中的某个部分。

我们需要一些游戏对象去代替这个时钟。选中菜单中的GameObject / Create Empty创建一个空的游戏物体(Empty GameObject),设置它的Position为(0,0,0),并且命名为“Clock”。然后再依次创建三个空物体(Empty GameObject)作为Clock的子物体,并且分别命名为“Hours”,“Minutes”,“Seconds”(不用说了吧,就是时针,分针,秒针)。确保它们的Position都为(0,0,0)。

GameObject是什么?

基本上,在场景中的所以物体都是一个GameObject(游戏对象)。它由一个名字(name),一个标签(tag),一个层(layer),一个Transform组件组成,它也可以标记为静态的(static)。它自身不做任何事情,只是一个空的容器。你可以通过给它添加组件让它变为有用的东西。

什么是子物体(child)?

你把一个物体A放到另一个物体B里面(通过在Hierarchy面板中拖拽),那么物体A就被称作是另一个物体B的子物体,也可以说是另一个物体B包含物体A,而物体B被称为父物体。父物体(就是B)的Transform被子物体给继承。

我们将使用简单的盒子去显示时钟的指针。通过菜单中的GameObject / Create Other / Cube 为每一个指针创建一个Cube作为该指针的子物体。为Hours的子物体(Cube)的position设置为(0,1,0),Scale设置为(0.5,2,0.5)。为Minutes的子物体(Cube)的position设置为(0,1.5,0),Scale设置为(0.25,3,0.25)。为Seconds的子物体(Cube)的position设置为(0,2,0),Scale设置为(0.1,4,0.1)。

9ccb63b84413aad0897b315740991000.png

Clock在Hierarchy中的层次结构

时钟动画

我们需要为Clock的动画创建一个脚本。创建一个新的C#脚本(在Assets面板中右键->Creat->C#Script),命名为“ClockAnimator”。双击打开该脚本,然后把默认的代码都删除了,我们重头再来过。

首先,我们通过使用UnityEngine命名空间来指明我们想要使用的类库。然后我们声明ClockAnimator类,它的访问权限是public(公有的),继承自MonoBehaviour。

using  UnityEngine;

public class ClockAnimator : MonoBehaviour

{

}

什么是namespace(命名空间)?

就像一个网站域名一样,但它是一行代码。例如:MonoBehaviour被定义在UnityEngine命名空间里,那么,它可以通过UnityEngine.MonoBehavour来访问。

就像域名一样,命名空间可以嵌套使用。最大的区别在于它的写法是相反的。如使用com.unity3d.forum替代forum.unity3d.com。例如,ArrayList类型存放在Collections命名空间下,而Collection存放在System命名空间下。所以,你需要通过System.Collections.ArrayList去访问到ArrayList。

通过声明使用一个命名空间,我们便不需要写那么复杂的代码来访问某个类了。例如,当我们使用using UnityEngine后,之前的UnityEngine.MonoBehaviour便可直接使用MonoBehaviour访问到。

什么是class(类)?

class是一个蓝图,它常用于创建对象,并存储在你的电脑内存中。蓝图定义了改对象包含了什么数据和它们如何运作。

什么是MonoBehaviour?

MonoBehaviour是一个位于UnityEngine命名空间下的类。如果你创建了一个类,你想要让一个类作为Unity组件来使用,那么你就必须让这个类继承自MonoBehaviour。它包含一些有用的材料(属性和方法)和让某些事情像Update()函数一样工作。

保存它(ClockAnimator类),然后把它添加到Clock对象上(通过直接拖拽或者在Hierarchy面板中选中Clock对象,然后点击Inspector面板中的Add Component按钮为其添加)。

5f87a8febb2dab926f012f1c41885284.png

为Clock添加ClockAnimator脚本

该类用于指针动画,我们需要访问他们的Transform组件。为每一个指针添加一个访问权限为public的Transform类型的变量,然后保存该类。

using  UnityEngine;
public class ClockAnimator : MonoBehaviour{
public Transform hours, minutes, seconds;
}

那些public(公有的)变量将成为组件属性,你可以指定一些相应的对象到该属性卡槽中。现在将相对应的Transform对象拖拽到卡槽中,如下图所示:

014cda3fe5f5b0a755be5ade9f7bd554.png

什么是变量?

所谓变量,就是它是可以改变的。它可以是一个引用类型(如class类型),也可以是一个值类型(如int类型)。一个变量必须指定它的类型,才能使用该变量做事情。

下一个,我们将添加一个Update()函数。这是一个特殊的方法,它将会在游戏运行时的每一帧都调用。我们将使用它去设置指针的旋转。

using  UnityEngine;

public class ClockAnimator : MonoBehaviour

{

public Transform hours, minutes, seconds;



private void Update()

{

    //暂时不做任何事情

}

}

什么是方法?

方法是一个行为数据块(语句块),在一个类中定义。它可以接收输入和返回一个输出。输入的定义位于方法名的后面,附带括号。这个方法的类型就是它的输出。如果没有输出,那么该方法的类型就是 void 。

Update()函数应该声明为public(公有的)吗?

我们不应该声明Update()函数为公有的(public),因为它不需要被其他类调用和修改。private(私有的)用于某些行为或属性不被外界访问,这样会让你的代码变得更安全,因为其它与它无关的东西都不会改变它。

我们在声明一个行为或属性的时候可以省略private关键字,因为C#默认访问权限就是private。

在保存脚本之前,编辑器将提示我们的组件有一个更新方法和显示一个复选框,该复选框允许我们禁用该脚本,但让,我们保持该脚本是开启的。

abd5698cdd9a39361f0836f6fcbbcd31.png

时针每一个小时旋转 360/12 度。分针每一分钟旋转 360/60 度。最后,秒钟每一秒钟旋转 360/60 度。让我们第一那些变量,这些变量都是private const float 类型。如下图所示:

using  UnityEngine;

public class ClockAnimator : MonoBehaviour

{

private const float

    hoursToDegrees = 360f/12f,

    mimutesToDegrees = 360f/60f,

    secondsToDegrees = 360f/60f;



public Transform hours, minutes, seconds;



private void Update()

{

    //暂时不做任何事情

}

}

const(常量)有什么特别之处?

const(常量)关键字表示一个永远改变不了的值。它的值将会在编译时计算,并且可以在任何地方直接引用到它。

每一次更新,我们都需要获得当前时间。System命名空间包含DateTime结构体,DateTime对我们非常有用。他有一个静态属性名Now,该Now包含了当前时间的数据。每次更新我们都需要去获取它的信息,然后用一个变量去存储它的信息。

using UnityEngine;

using System;

public class ClockAnimator : MonoBehaviour

{

private const float

    hoursToDegrees = 360f/12f,

    mimutesToDegrees = 360f/60f,

    secondsToDegrees = 360f/60f;



public Transform hours, minutes, seconds;



private void Update()

{

    DateTime time = DateTime.Now;

}

}

什么是struct(结构体)?

结构体是一个蓝图,和class(类)和类似。区别是它可以在任何地方声明,它是一个值类型(如int),而不是一个对象。它不能作为对象来使用。

什么是property(属性)?

property(属性)是一个访问器,它可能是只读或只写。

注意Unity编辑器的属性卡槽也可以看做是一个属性,但是它们两个不是相同的概念。

获得指针的旋转,我们想要改变他们的本地旋转。我们通过使用Quaternion(四元素)直接设置指针的localRotation。Quaternion(四元素)有一个非常好的方法(函数),我们可以使用它去定义一个任意的旋转。

因为我们目视方向是Z轴,Unity使用的是左手坐标系,所以旋转必须围绕-Z轴旋转。

using UnityEngine;

using System;

public class ClockAnimator : MonoBehaviour

{

private const float

    hoursToDegrees = 360f/12f,

    mimutesToDegrees = 360f/60f,

    secondsToDegrees = 360f/60f;



public Transform hours, minutes, seconds;



private void Update()

{

    DateTime time = DateTime.Now;



    hours.localRotation =

        Quaternion.Euler(0f, 0f, time.Hour*-hoursToDegrees);

    minutes.localRotation =

        Quaternion.Euler(0f, 0f, time.Minute * -mimutesToDegrees);

    seconds.localRotation =

        Quaternion.Euler(0f, 0f, time.Second * -secondsToDegrees);



}
}
44c02447e2f1c52f3ef51a5f4db88c6b.png

时钟显示为12:44

什么是Quatermion(四元素)?

Quatermion使用它去表示一个3D旋转。虽然比简单的三维向量要难以理解,但是他们有一些有用的特性。Quatermion结构体包含是UnityEngine命名空间下。

改善时钟

在播放模式中,我们的时钟将显示当前的时间。不管怎样,它的行为非常像一个数字时钟,因为它只显示离散的步骤。让我们包括一个选项来更好的模拟显示时间吧。让我们在脚本中添加一个名为“analog”的公有(public)bool类型的变量。使用该变量去确定在Update()函数中做些事情。我们可以在编辑器中切换这个变量的值,即使在游戏运行时。

using UnityEngine;

using System;

public class ClockAnimator : MonoBehaviour

{

private const float

    hoursToDegrees = 360f/12f,

    mimutesToDegrees = 360f/60f,

    secondsToDegrees = 360f/60f;



public Transform hours, minutes, seconds;



public bool analog;



private void Update()

{

    DateTime time = DateTime.Now;



    hours.localRotation =

        Quaternion.Euler(0f, 0f, time.Hour*-hoursToDegrees);

    minutes.localRotation =

        Quaternion.Euler(0f, 0f, time.Minute * -mimutesToDegrees);

    seconds.localRotation =

        Quaternion.Euler(0f, 0f, time.Second * -secondsToDegrees);



}
}
6189008b6a4df715f059ac1e1440f41e.png

对于analog选项,我们需要一个稍微不同的方法。我们将使用DateTime.Now.TimeOfDay来代替DateTime.Now。它是一个 TimeSpan 。这让我们很容易的访问部分运行时间。因为它是一个double类型的值。因此我们需要把它强制转换成float类型。

using UnityEngine;

using System;

public class ClockAnimator : MonoBehaviour

{

private const float

    hoursToDegrees = 360f/12f,

    mimutesToDegrees = 360f/60f,

    secondsToDegrees = 360f/60f;



public Transform hours, minutes, seconds;



public bool analog;



private 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 * -mimutesToDegrees);

        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 * -mimutesToDegrees);

        seconds.localRotation =

            Quaternion.Euler(0f, 0f, time.Second * -secondsToDegrees);

    }

}

}
9a4e9f0eab9a7cabf9d8798573474a69.png

时钟在analog模式下显示为12:56

现在,我们的时钟就做好了!!

妈蛋,终于完成了,累死wo了。It's so tired!!!!

PS:这篇主要是面向新手,请大神勿喷,也不要觉得这个是一个烂文章,谢谢。

-- END --

706ba3ce115112d2069ff2cd55c21f66.gif

  • unity实战之大主宰
  • Unity手游实战:从0开始SLG——概览

  • unity之随机数

  • unity实战之战棋小游戏

>>> 点击进入技术讨论群 <<<

7a26fee4d17660e83ca285d025e4736a.gif ▽想知道更多?

da166da3b5ce68b4dcce3df35a067b89.png

长按/扫码关注我吧↑↑↑

觉得不错就点个在看吧!

cc6d0039ad1fef83ecf34e117ef8621d.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值