上一教程中我们完成了场景设置和坦克设置,今天接着上一教程继续
传送门:unity官方教程-TANKS(一)
在我们设置好了坦克预置后,接下来就是相机设置了
一、相机配置
1、在Hierarchy面板中创建一个空物体,重命名为CameraRig,选中该物体后在Inspector面板重置它的位置属性,点击图中位置,然后将Rotation属性设置为(40,60,0)
2、在Hierarchy面板中将Main Camera拖动到CameraRig上使其成为CameraRig的子物体,设置Main Camera的Position属性为(0,0,-65),Rotation属性为(0,0,0)
3、为了使相机跟随坦克移动,需要编程实现(代码为Scripts/Camera/CameraControll.cs),因为是两台坦克对战,相机需要照顾到两台坦克,即找到两台坦克的中间位置,将相机移动到那个位置
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;
}
4、在两台坦克距离变远或变近时,只移动相机位置是不够的,同时需要将相机拉近或拉远以防止坦克跑出镜头,这一步是通过调整相机的Size属性实现
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实现的,跟着步骤走就可以实现出效果,但对于每一步骤为什么这么做则需要自己实验看看了
1、在Hierarchy中创建一个UI->Slider,选择EventSystem,将Standalone Input Module的Horizontal Axis属性改为HorizontalUI,Vertical Axis属性改为VerticalUI
2、选择Canvas,将Canvas Scaler组件的Reference Pixels per Unit改为1,将Canvas组件的Render Mode改为World Space
3、将Canvas物体拖拽到Tank上,选择Canvas,修改其Position属性为(0,0.1,0),Width属性为3.5,Height属性为3.5,Rotation属性为(90,0,0),保存场景
4、展开Canvas的所有子物体,删掉HandleSlideArea,将其它子物体全部选中,点击图示位置,按住Alt键,同时点击右下角的选项
5、选择Slider物体,取消Interactable,修改Transition为none,调整Max Value和Value为100,重命名Slider为HealthSlider
6、选中Background,将Image组件的Image Source属性修改为Health Wheel,修改Color属性的Alpha值为80
7、选中Fill物体,将Image组件的Image Source属性修改为Health Wheel,修改Color属性的Alpha值为150,Image Type属性为Filled,Fill Origin属性为Left,取消Clockwise
8、在Scripts/UI文件夹找到UIDireactionControl.cs脚本,拖拽到HealthSlider物体上
9、选中Tank物体,点击Inspector面板的Apply,将修改运用到预置
三、爆炸特效
1、找到Prefabs文件夹下的TankExplosion,拖拽到Hierarchy中,给其添加一个AudioSource组件,AudioClip属性选择为TankExplosion,取消Play On Awake
2、选中TankExplosion,点击Inspector面板中的Apply更新预置
3、从Hierarchy中删除TankExplosion
四、坦克生命值脚本控制
1、找到Scripts/Tank/TankHealth.cs脚本,替换为以下内容
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();
// Get a reference to the audio source on the instantiated prefab.
m_ExplosionAudio = m_ExplosionParticles.GetComponent();
// 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);
}
}
2、将脚本拖拽到Tank物体上,然后拖拽HealthSlider到TankHealth的Slider属性,Fill物体到FillImage属性,TankExplosion到ExplosionPrefab属性
3、选中Tank物体,点击Inspector面板的Apply,将修改应用到预置,保存场景
以上就是今天的主要内容了,下期教程继续。。。