上一教程中咱们完成了场景设置和坦克设置,今天接着上一教程继续
传送门:unity官方教程-TANKS(一)react
在咱们设置好了坦克预置后,接下来就是相机设置了编程
一、在Hierarchy面板中建立一个空物体,重命名为CameraRig,选中该物体后在Inspector面板重置它的位置属性,点击图中位置,而后将Rotation属性设置为(40,60,0)segmentfault
二、在Hierarchy面板中将Main Camera拖动到CameraRig上使其成为CameraRig的子物体,设置Main Camera的Position属性为(0,0,-65),Rotation属性为(0,0,0)
三、为了使相机跟随坦克移动,须要编程实现(代码为Scripts/Camera/CameraControll.cs),由于是两台坦克对战,相机须要照顾到两台坦克,即找到两台坦克的中间位置,将相机移动到那个位置app
private void FindAveragePosition() { Vector3 averagePos = new Vector3(); int numTargets = 0; //找到两台坦克的位置 for (int i = 0; i < m_Targets.Length; i++) { // 坦克 if (!m_Targets[i].gameObject.activeSelf) continue; // 两台坦克位置相加 averagePos += m_Targets[i].position; numTargets++; } //求坦克平均位置 if (numTargets > 0) averagePos /= numTargets; // 保持y轴位置不变 averagePos.y = transform.position.y; m_DesiredPosition = averagePos; }
四、在两台坦克距离变远或变近时,只移动相机位置是不够的,同时须要将相机拉近或拉远以防止坦克跑出镜头,这一步是经过调整相机的Size属性实现ide
private float FindRequiredSize() { // 世界坐标系转为相机坐标系 Vector3 desiredLocalPos = transform.InverseTransformPoint(m_DesiredPosition); float size = 0f; //找到两台坦克中较远的那个,为了使它能进入相机镜头 for (int i = 0; i < m_Targets.Length; i++) { if (!m_Targets[i].gameObject.activeSelf) continue; // 将坦克位置从世界坐标系转为相机坐标系 Vector3 targetLocalPos = transform.InverseTransformPoint(m_Targets[i].position); //计算坦克与相机的位置差 Vector3 desiredPosToTarget = targetLocalPos - desiredLocalPos; // 根据位置差找出合适的Size size = Mathf.Max(size, Mathf.Abs(desiredPosToTarget.y)); size = Mathf.Max(size, Mathf.Abs(desiredPosToTarget.x) / m_Camera.aspect); } // 添加适当的距离,不然坦克将出如今屏幕边缘 size += m_ScreenEdgeBuffer; size = Mathf.Max(size, m_MinSize); return size; }
效果如图,绿色表明坦克的生命值,该效果是经过UI实现的,跟着步骤走就能够实现出效果,但对于每一步骤为何这么作则须要本身实验看看了ui
一、在Hierarchy中建立一个UI->Slider,选择EventSystem,将Standalone Input Module的Horizontal Axis属性改成HorizontalUI,Vertical Axis属性改成VerticalUI
二、选择Canvas,将Canvas Scaler组件的Reference Pixels per Unit改成1,将Canvas组件的Render Mode改成World Space
三、将Canvas物体拖拽到Tank上,选择Canvas,修改其Position属性为(0,0.1,0),Width属性为3.5,Height属性为3.5,Rotation属性为(90,0,0),保存场景
四、展开Canvas的全部子物体,删掉HandleSlideArea,将其它子物体所有选中,点击图示位置,按住Alt键,同时点击右下角的选项this
五、选择Slider物体,取消Interactable,修改Transition为none,调整Max Value和Value为100,重命名Slider为HealthSlider
六、选中Background,将Image组件的Image Source属性修改成Health Wheel,修改Color属性的Alpha值为80
七、选中Fill物体,将Image组件的Image Source属性修改成Health Wheel,修改Color属性的Alpha值为150,Image Type属性为Filled,Fill Origin属性为Left,取消Clockwise
八、在Scripts/UI文件夹找到UIDireactionControl.cs脚本,拖拽到HealthSlider物体上
九、选中Tank物体,点击Inspector面板的Apply,将修改运用到预置spa
一、找到Prefabs文件夹下的TankExplosion,拖拽到Hierarchy中,给其添加一个AudioSource组件,AudioClip属性选择为TankExplosion,取消Play On Awake
二、选中TankExplosion,点击Inspector面板中的Apply更新预置
三、从Hierarchy中删除TankExplosion3d
一、找到Scripts/Tank/TankHealth.cs脚本,替换为如下内容code
using UnityEngine; using UnityEngine.UI; public class TankHealth : MonoBehaviour { public float m_StartingHealth = 100f; // The amount of health each tank starts with. public Slider m_Slider; // The slider to represent how much health the tank currently has. public Image m_FillImage; // The image component of the slider. public Color m_FullHealthColor = Color.green; // The color the health bar will be when on full health. public Color m_ZeroHealthColor = Color.red; // The color the health bar will be when on no health. public GameObject m_ExplosionPrefab; // A prefab that will be instantiated in Awake, then used whenever the tank dies. private AudioSource m_ExplosionAudio; // The audio source to play when the tank explodes. private ParticleSystem m_ExplosionParticles; // The particle system the will play when the tank is destroyed. private float m_CurrentHealth; // How much health the tank currently has. private bool m_Dead; // Has the tank been reduced beyond zero health yet? private void Awake() { // Instantiate the explosion prefab and get a reference to the particle system on it. m_ExplosionParticles = Instantiate(m_ExplosionPrefab).GetComponent<ParticleSystem>(); // Get a reference to the audio source on the instantiated prefab. m_ExplosionAudio = m_ExplosionParticles.GetComponent<AudioSource>(); // Disable the prefab so it can be activated when it's required. m_ExplosionParticles.gameObject.SetActive(false); } private void OnEnable() { // When the tank is enabled, reset the tank's health and whether or not it's dead. m_CurrentHealth = m_StartingHealth; m_Dead = false; // Update the health slider's value and color. SetHealthUI(); } public void TakeDamage(float amount) { // Reduce current health by the amount of damage done. m_CurrentHealth -= amount; // Change the UI elements appropriately. SetHealthUI(); // If the current health is at or below zero and it has not yet been registered, call OnDeath. if (m_CurrentHealth <= 0f && !m_Dead) { OnDeath(); } } private void SetHealthUI() { // Set the slider's value appropriately. m_Slider.value = m_CurrentHealth; // Interpolate the color of the bar between the choosen colours based on the current percentage of the starting health. m_FillImage.color = Color.Lerp(m_ZeroHealthColor, m_FullHealthColor, m_CurrentHealth / m_StartingHealth); } private void OnDeath() { // Set the flag so that this function is only called once. m_Dead = true; // Move the instantiated explosion prefab to the tank's position and turn it on. m_ExplosionParticles.transform.position = transform.position; m_ExplosionParticles.gameObject.SetActive(true); // Play the particle system of the tank exploding. m_ExplosionParticles.Play(); // Play the tank explosion sound effect. m_ExplosionAudio.Play(); // Turn the tank off. gameObject.SetActive(false); } }
二、将脚本拖拽到Tank物体上,而后拖拽HealthSlider到TankHealth的Slider属性,Fill物体到FillImage属性,TankExplosion到ExplosionPrefab属性
三、选中Tank物体,点击Inspector面板的Apply,将修改应用到预置,保存场景
以上就是今天的主要内容了,下期教程继续。。。