今天一天都在跟队长一起研究Timeline,主要用来制作游戏剧情过场动画。
了解过后感觉Timeline功能很强大!
主要也用了Virtual Camera来锁定人物或场景之间的镜头,可在Timeline里实现运镜的效果(平滑过渡)。
关于剧情对话UI:
1.UI----Canvas-----Scale with screen size(自适应)---调整分辨率
2.UI-----Panel----(换成2D视角)调整对话框大小---Alt + Shift + 位置(自动占满对齐)---适当调整
3.UI----Text--- 加入文字? 【设置颜色,例如:<color=red>XXXX</color>】
---添加Outline组件:加深清晰度
4.创建空物体:UIManager-----创建脚本UIManager
(负责UI对话的开启与关闭)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//负责UI对话的开启和关闭
public class UIManag : MonoBehaviour
{
public static UIManag instance;
public GameObject dialogueBox; //开启或关闭对话窗口
public Text characterNameText1;
public Text dialogueLineText;
public GameObject spacebar;
private void Awake()
{
//将UIManager设置为单例模式
if (instance == null)
{
instance = this;
}
else
{
if (instance != this)
{
Destroy(gameObject);
}
}
DontDestroyOnLoad(gameObject);
}
//开启or关闭对话窗口
public void ToggleDialogueBox(bool _isActive)
{
dialogueBox.gameObject.SetActive(_isActive);
}
public void ToggleSpaceBar(bool _isActive)
{
spacebar.gameObject.SetActive(_isActive);
}
//以上两种方法也可以写成一个,但是不方便外部调用
/*public void ToggleFoo(GameObject _foo, bool _isActive)
{
_foo.gameObject.SetActive(_isActive);
}*/
//导入对话者名字(如果勾选了Best Fit则不用加size)
public void SetupDialogue(string _name, string _line, int _size)
{
//赋值台词、名字
characterNameText1.text = _name;
dialogueLineText.text = _line;
dialogueLineText.fontSize = _size;
//显示对话框
ToggleDialogueBox(true);
}
}
关于Virtual Camera:
1.锁定镜头画面:锁定Solo;(否则其他VirCam可能会也变成此画面)
2.Ctrl + Shift + F 确定画面;
3.将Virtual Camera加入Timeline时别忘了需要将<主相机>放入,作为CinemacheineBrain。
关于Timeline:
1.创建空物体----Timeline? (Window - Sequencing --显示Timeline标签)
2.Timeline窗口---Create---可加入人物动画、虚拟相机、剧情框与文字……等。
?注:放上去的同时都不要忘了把主对象放入左边Track List中。
?3.建立脚本----(实现在Timeline中的剧情对话功能)
a. 创建自定义对话轨道
using UnityEngine;
using UnityEngine.Timeline;
//[TrackBindingType(typeof(Rigidbody))] 绑定挂在类型,如:刚体
[TrackColor(255/255f, 191/255f, 0)] //设置轨道标签颜色(对应的RGB数值
[TrackClipType(typeof(DialogueClip))]
//对话系统
public class DialogueTrack : TrackAsset
{
}
?b.建立出配对轨道的对话Clip片段
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
//更直接地访问底层动画系统的接口
public class DialogueClip : PlayableAsset
{
public DialogueBehavior template = new DialogueBehavior();
public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
{
var playable = ScriptPlayable<DialogueBehavior>.Create(graph, template);
return playable;
}
}
?c.建立对话行为:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
[System.Serializable] //序列化之后,才能在窗口显示
public class DialogueBehavior : PlayableBehaviour
{
//获取playableDirector:负责动画开启、暂停
private PlayableDirector playableDirector;
public string characterName;
[TextArea(8,1)] public string dialogueLine; //[更大的文字编辑空间]
public int dialogueSize;//字体大小
private bool isClipPlayed; //是否这个对话Clip片段,已经播放结束了
public bool requirePause; //用户设置:这个对话完成之后,是否需要玩家按下“空格键”才能继续动画
private bool pauseScheduled; //暂停的判断条件
public override void OnPlayableCreate(Playable playable)
{
playableDirector = playable.GetGraph().GetResolver() as PlayableDirector;
}
//类似Update,每一帧都会调用
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
//片段还没有播放
if (isClipPlayed == false && info.weight > 0)
{
UIManag.instance.SetupDialogue(characterName, dialogueLine, dialogueSize);
//若之前设置好此片段需要暂停
if (requirePause)
pauseScheduled = true;
isClipPlayed = true; //此片段可以播放
}
}
public override void OnBehaviourPause(Playable playable, FrameData info)
{
//如果资源处于静止、暂停状态
isClipPlayed = false;
Debug.Log("Clip is Stoooooooooooop");
if (pauseScheduled)
{
pauseScheduled = false; //先关闭开关
//Marker Pause TIMELINE 暂停Timeline播放
GameManager.instance.PauseTimeline(playableDirector);
}
else
{
UIManag.instance.ToggleDialogueBox(false);
}
}
}
4.通过人物移动到某位置(空物体---碰撞体)触发剧情播放:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
public class TriggerArea : MonoBehaviour
{
public PlayableDirector playableDirector;
private void OnTriggerEnter(Collider other) // other.tag == "Player"开销相对高
{
if (other.CompareTag("Player"))
{
playableDirector.Play(); //播放过场动画
GameManager.instance.gameMode = GameManager.GameMode.GamePlay;
}
}
}
|