Unity脚本(三)

视频教程:https://www.bilibili.com/video/BV12s411g7gU?p=128 

目录

Time

Prefab 

Animation


Time

Time.time:自应用程序启动以来,每帧的开始时间(只读)  

Time.deltaTime:每帧间隔,或说完成一帧的时间(等于当前帧的Time.time-下一帧的Time.time)

public float speed=100;

void Update()
{
        transform.Rotate(0,speed*Time.deltaTime,0);
        //旋转/移动速度*每帧间隔,以保证旋转/移动速度不受渲染影响
}

Time.timeScale:时间的缩放,可用于慢动作效果或加快应用程序速度

ps:当设置为1.0时,时间流逝的速度与实时时间一样快;当设置为0.5时,时间比实时慢2倍 

Time.unscaledTime:不收缩放影响的每帧间隔

//渲染时执行,不受TimeScale影响
void Update()
{
    //transform.Rotate(0, speed * Time.deltaTime, 0);
}

//固定0.02s执行一次,与渲染无关,受TimeScale影响
void FixedUpdate()
{
    //this.transform.Rotate(0, speed * Time.fixedDeltaTime, 0);
}

void OnGUI()
{
    if (GUILayout.Button("暂停游戏"))
    {
        Time.timeScale = 0;
    }

    if (GUILayout.Button("继续游戏"))
    {
        Time.timeScale = 1;
    }
}

尽管Update的执行不受timeScale的影响,但是在运行后,Update中编写的Transform.Rotate方法仍会受到timeScale的影响,这是因为Time.deltaTime受到了timeScale的影响,若修改代码不乘Time.deltaTime,则按下“暂停游戏”可使物体停止旋转

transform.Rotate(0, speed, 0);

使场景中的某些物体不受“暂停”的影响

public float speed = 100;

void Update()
{
        transform.Rotate(0, speed * Time.unscaledTime, 0);     
}

void OnGUI()
{
    if (GUILayout.Button("暂停游戏"))
    {
        Time.timeScale = 0;
    }

    if (GUILayout.Button("继续游戏"))
    {
        Time.timeScale = 1;
    }
}

Time.frameCount:自游戏开始以来的总帧数(只读)

Time.realtimeSinceStartup:游戏开始以来的实际时间(只读)

可以使用如下代码了解Time.timeScale,Time.unscaledTime及Time.realtimeSinceStartup的区别。运行后点击“暂停游戏”按钮,可以发现除了变量a,其余变量的值仍在累积

public float a;
public float b;
public float c;

void Update()
{
    a=Time.time;
    b=Time.unscaledTime;
    c=Time.realtimeSinceStartup;
}

void OnGUI()
{
    if (GUILayout.Button("暂停游戏"))
    {
        Time.timeScale = 0;
    }

    if (GUILayout.Button("继续游戏"))
    {
        Time.timeScale = 1;
    }
}

每1秒变化一次的时钟

难点:因为Update的执行受渲染的影响,使每帧的时间间隔不同(但一般仍在0.02左右)

方法1:

private float nextTime = 1;

void Update()
{
    if (Time.time >= nextTime)
    {
        second--;
        textTimer.text = string.Format($"{second / 60:d2}:{second % 60:d2}");
        nextTime = Time.time + 1;
    }
}

方法2:

private float totalTime = 1;

void Update()
{
    totalTime+=Time.deltaTime;
    if (totalTime>1)
    {
        second--;
        textTimer.text = string.Format($"{second / 60:d2}:{second % 60:d2}");
        totalTime-=1;
    }
}

 方法3:

void Start()
{
    textTimer = GetComponent<TMP_Text>();
    InvokeRepeating("Timer", 1, 1);
}

void Timer()
{
    if (second <= 0)
    {
        CancelInvoke("Timer");
    }
    second--;
    textTimer.text = string.Format($"{second / 60:d2}:{second % 60:d2}");
}

MonoBehaviour.InvokeRepeating(string methodName, float time, float repeatRate):在time 秒后调用methodName方法,然后每repeatRate秒调用一次

methodName调用的方法名
timen秒后开始调用
repeatRate每n秒重复一次。

MonoBehaviour.CancelInvoke:取消该MonoBehaviour上的所有Invoke调用,或取消该行为上所有名为methodName的Invoke调用

Prefab 

一种资源类型,可以多次在场景进行实例。且对预制件的修改,可以同步到所有实例,从而提高开发效率,当若单独修改实例的属性值,则该值不再随预制件变化 

将处于Hierarchy面板的游戏对象拖入Project面板

 

Open:在场景中打开预制件 

Select:通过预制件实例选择对应预制件

Revert All:放弃对实例属性值的修改,并还原预制件属性值

Apply All:将某一实例的修改应用至预制件和其他所有实例

Animation

Animation.CrossFade:在一定时间内淡入名称为name的动画并使其他动画淡出

Animation.Play:播放不带有任何混合的动画

Animation.PlayQueued:在前一个动画播放完成之后直接播放下一个动画(按指定的序列一个接一个地播放动画)

录制步骤

1.点击录制按钮,开始录制动画

2.添加关键帧Add Property,选择组件类型

3.选择关键帧,调整时间点

4.在Scene或 Inspector面板设置属性

5.点击录制按钮,结束录制动画

制作开门动画

在场景中使用一个Cube(Base)作为门的模型,用一个空物体(Door)作为门的旋转轴并使其作为前者的父级

 

 调整空物体(Door)的位置,使其Z轴与门的旋转轴重合

  

选择游戏对象Door,并进入Window-->Animation-->Animation创建名为Door的动画后,点击左上角的红点进入录制模式;点击Add Property选择Transform下的Rotation属性(点击右侧的+号)

添加相应属性后,默认的动画长度为0:00到1:00,可拖动末尾的关键帧至适当的位置改变动画长度,或对其按下右键选以删除末尾的关键帧(对关键帧上右键选择Delete Key)后,在合适位置双击添加新的关键帧(亦或是在合适的时间线上右键选择Add Key)

 

返回Inspector面板即可发现相应的属性的显示框成红色,在选择时间线末尾帧的情况下,将Rotation的Y值设置为90(绕Y轴选择90度)

ps:如生成了Animator则卸载该组件并挂载Animation组件后,按上图进行设置;一定要挂载碰撞组件Box Collider并点击Edit Collider调整配置盒,否则下文脚本中的OnMouseDown()无法生效

可以选择下方的Curves显示动画的细节

编写脚本Door并将其挂载至游戏对象Door上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Door : MonoBehaviour
{
    public bool isOpen = false;
    public string animName;
    private Animation anim;

    private void Start()
    {
        anim = GetComponent<Animation>();
    }

    private void OnMouseDown()
    {
        if (isOpen)
        {
            if (anim.isPlaying == false)
            {
                anim[animName].time = anim[animName].length;
            }
            anim[animName].speed = -1;

        }
        else
        {
            anim[animName].speed = 1;

        }
        anim.Play(animName);
        isOpen = !isOpen;
    }
}

Animation.isPlaying:当前动画是否正在播放

Animation.time:该动画的当前时间

Animation.length:该动画的长度

ps:对于新版不使用Animator控制动画需进行如下设置,否则会弹出警告

The AnimationClip ‘Door‘ used by the Animation component ‘Door‘ must be marked as Legacy

在Inspector面板右上方的菜单中选择Debug模式后,勾选Legacy 

  

 

Wrap Mode

包裹模式,决定动画结束后的处理方式  

Default 默认 :使用动画剪辑中的处理方法

Once 播放一次:播放到头后停止

Loop 循环播放:播放到头后再重头播放

PingPong 乒乓播放:播放到头后再反向播放

Clamp Forever 固定永久:播放到头后永远播放最后一帧

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值