unity官方教程-TANKS(一)

unity官方教程TANKS,难度系数中阶。
跟着官方教程学习Unity,通过本教程你可以学会使用Unity开发游戏的基本流程。

clipboard.png

一、环境

Unity 版本 > 5.2
Asset Store 里面搜索 Tanks!Tutorial ,下载导入

二、项目设置

为了便于开发,很多时候我们选用的窗口布局是 2by3 Layout,然后将 Project 面板拖动到 Hierarchy 面板下面,如下图所示

clipboard.png

三、场景设置

项目设置完毕后,就进入场景设置环节

1、新建一个场景,命名为 Main
2、删除场景中的 Directional Light
3、找到 Prefabs 文件夹下的 LevelArt,将其拖入 Hierarchy 内,这个 prefab 是我们的游戏地形
4、打开菜单 Windows->Lighting->Settings,取消 Auto Generate 和 Baked GI,将 Environment Lighting Source 改为 Color,并将颜色设置为(72,62,113),点击 Generate Lighting,这一步主要是渲染设置
5、调整 Main Camera 位置为 (-43,42,-25),旋转属性为 (40,60,0),投影改为正交 Orthographic,Clear Flags 改为 Solid Color ,Background 颜色设置为(80,60,50),Clear Flags不设置也可以,这个设置主要影响的是相机移动到看不到场景内的物体时屏幕显示的天空盒还是自己设置的 Solid Color 颜色

四、坦克设置

现在要往场景里加坦克了

1、在 Models 文件夹里面找到 Tank,将其拖拽到 Hierarchy 中
2、选中 Tank,在Inspector面板将 Layer 设置为 Players,跳出对话框时选 No,this object only
3、给 Tank 添加一个 Rigidbody Component,展开 Constraints 选项,勾选 Freeze Position Y 和 Freeze Rotation X Z,因为地面位于 XZ 平面,所以限定坦克不能在 Y 方向移动并且只能沿 Y 轴转动
4、给 Tank 添加一个 Box Collider Component,将其中心 Center 调整为(0,0.85,0),尺寸 Size 调整为(1.5,1.7,1.6)
5、给 Tank 添加两个 Audio Source Component,将第一个 Audio Source 的 AudioClip 属性填充为 Engine Idle(坦克不动时的音频),并勾选 Loop,将第二个 Audio Source 的 Play On Awake 取消
6、选中 Project 面板的 Prefabs 文件夹,将 Tank 拖入到该文件夹,至此我们就创建好了坦克 Prefab
7、将 Prefabs 文件夹中的 DustTrail 拖到 Hierarchy 面板中的 Tank 物体上,使其成为 Tank 的子物体,并Crtl + D(windows)复制一个,然后重命名为 LeftDustTrail 和 RightDustTrail,这是特效 - 坦克运动过程地面扬起的土
8、调整 LeftDustTrail 的 position 为(-0.5,0,-0.75),RightDustTrail 的position 为(0.5,0,-0.75)

以上过程便制作好了游戏主角 Tank,下面就要编程控制它运动了

1、找到 ScriptsTank 文件夹下的 TankMovement.cs,将其拖入到 Tank 物体上,打开 TankMovement.cs

public class TankMovement : MonoBehaviour
{public int m_PlayerNumber = 1;         public float m_Speed = 12f;            public float m_TurnSpeed = 180f;       public AudioSource m_MovementAudio;    public AudioClip m_EngineIdling;       public AudioClip m_EngineDriving;      public float m_PitchRange = 0.2f;/*private string m_MovementAxisName;     private string m_TurnAxisName;         private Rigidbody m_Rigidbody;         private float m_MovementInputValue;    private float m_TurnInputValue;        private float m_OriginalPitch;         private void Awake(){m_Rigidbody = GetComponent<Rigidbody>();}private void OnEnable (){m_Rigidbody.isKinematic = false;m_MovementInputValue = 0f;m_TurnInputValue = 0f;}private void OnDisable (){m_Rigidbody.isKinematic = true;}private void Start(){m_MovementAxisName = "Vertical" + m_PlayerNumber;m_TurnAxisName = "Horizontal" + m_PlayerNumber;m_OriginalPitch = m_MovementAudio.pitch;}*/private void Update(){// Store the player's input and make sure the audio for the engine is playing.}private void EngineAudio(){// Play the correct audio clip based on whether or not the tank is moving and what audio is currently playing.}private void FixedUpdate(){// Move and turn the tank.}private void Move(){// Adjust the position of the tank based on the player's input.}private void Turn(){// Adjust the rotation of the tank based on the player's input.}
}

里面已经有一些代码了,下面我们就对其扩充来控制坦克移动
Unity控制物体移动的方法主要有两种:
①非刚体(Update)
obj.transform.position = obj.transform.position+移动向量*Time.deltaTime;
obj.transform.Translate(移动向量*Time.deltaTime);
②刚体(FixedUpdate)
GetComponent<Rigidbody>().velocity
GetComponent<Rigidbody>().AddForce
GetComponent<Rigidbody>().MovePosition

由于我们的坦克是刚体,且移动被限制在了 XZ 平面,此时最好的方式是采用 MovePosition
获取用户输入

    private void Start(){//在菜单Edit->Project Settings->Input设置,默认玩家1左右移动按键是 a 和 d,前后按键是 w 和 sm_MovementAxisName = "Vertical" + m_PlayerNumber;m_TurnAxisName = "Horizontal" + m_PlayerNumber;}private void Update(){//获取用户通过按键 w 和 s 的输入量m_MovementInputValue = Input.GetAxis(m_MovementAxisName);//获取用户通过按键 a 和 d 的输入量m_TurnInputValue = Input.GetAxis(m_TurnAxisName);}

移动和转动

    private void Move(){Vector3 movement = transform.forward * m_MovementInputValue * m_Speed * Time.deltaTime;m_Rigidbody.MovePosition(m_Rigidbody.position + movement);}private void Turn(){float turn = m_TurnInputValue * m_TurnSpeed * Time.deltaTime;// 沿y轴转动Quaternion turnRotation = Quaternion.Euler(0f, turn, 0f);m_Rigidbody.MoveRotation(m_Rigidbody.rotation * turnRotation);}

音效控制

    private void EngineAudio(){// 坦克是静止的if (Mathf.Abs(m_MovementInputValue) < 0.1f && Mathf.Abs(m_TurnInputValue) < 0.1f){// 若此时播放的是坦克运动时的音效if (m_MovementAudio.clip == m_EngineDriving){m_MovementAudio.clip = m_EngineIdling;m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);//控制音频播放速度m_MovementAudio.Play();}}else{if (m_MovementAudio.clip == m_EngineIdling){m_MovementAudio.clip = m_EngineDriving;m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);//控制音频播放速度m_MovementAudio.Play();}}}

TankMovement.cs 完整代码

using UnityEngine;public class TankMovement : MonoBehaviour
{public int m_PlayerNumber = 1;              // Used to identify which tank belongs to which player.  This is set by this tank's manager.public float m_Speed = 12f;                 // How fast the tank moves forward and back.public float m_TurnSpeed = 180f;            // How fast the tank turns in degrees per second.public AudioSource m_MovementAudio;         // Reference to the audio source used to play engine sounds. NB: different to the shooting audio source.public AudioClip m_EngineIdling;            // Audio to play when the tank isn't moving.public AudioClip m_EngineDriving;           // Audio to play when the tank is moving.public float m_PitchRange = 0.2f;           // The amount by which the pitch of the engine noises can vary.private string m_MovementAxisName;          // The name of the input axis for moving forward and back.private string m_TurnAxisName;              // The name of the input axis for turning.private Rigidbody m_Rigidbody;              // Reference used to move the tank.private float m_MovementInputValue;         // The current value of the movement input.private float m_TurnInputValue;             // The current value of the turn input.private float m_OriginalPitch;              // The pitch of the audio source at the start of the scene.private void Awake(){m_Rigidbody = GetComponent<Rigidbody>();}private void OnEnable(){// When the tank is turned on, make sure it's not kinematic.m_Rigidbody.isKinematic = false;// Also reset the input values.m_MovementInputValue = 0f;m_TurnInputValue = 0f;}private void OnDisable(){// When the tank is turned off, set it to kinematic so it stops moving.m_Rigidbody.isKinematic = true;}private void Start(){// The axes names are based on player number.m_MovementAxisName = "Vertical" + m_PlayerNumber;m_TurnAxisName = "Horizontal" + m_PlayerNumber;// Store the original pitch of the audio source.m_OriginalPitch = m_MovementAudio.pitch;}private void Update(){// Store the value of both input axes.m_MovementInputValue = Input.GetAxis(m_MovementAxisName);m_TurnInputValue = Input.GetAxis(m_TurnAxisName);EngineAudio();}private void EngineAudio(){// If there is no input (the tank is stationary)...if (Mathf.Abs(m_MovementInputValue) < 0.1f && Mathf.Abs(m_TurnInputValue) < 0.1f){// ... and if the audio source is currently playing the driving clip...if (m_MovementAudio.clip == m_EngineDriving){// ... change the clip to idling and play it.m_MovementAudio.clip = m_EngineIdling;m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);m_MovementAudio.Play();}}else{// Otherwise if the tank is moving and if the idling clip is currently playing...if (m_MovementAudio.clip == m_EngineIdling){// ... change the clip to driving and play.m_MovementAudio.clip = m_EngineDriving;m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);m_MovementAudio.Play();}}}private void FixedUpdate(){// Adjust the rigidbodies position and orientation in FixedUpdate.Move();Turn();}private void Move(){// Create a vector in the direction the tank is facing with a magnitude based on the input, speed and the time between frames.Vector3 movement = transform.forward * m_MovementInputValue * m_Speed * Time.deltaTime;// Apply this movement to the rigidbody's position.m_Rigidbody.MovePosition(m_Rigidbody.position + movement);}private void Turn(){// Determine the number of degrees to be turned based on the input, speed and time between frames.float turn = m_TurnInputValue * m_TurnSpeed * Time.deltaTime;// Make this into a rotation in the y axis.Quaternion turnRotation = Quaternion.Euler(0f, turn, 0f);// Apply this rotation to the rigidbody's rotation.m_Rigidbody.MoveRotation(m_Rigidbody.rotation * turnRotation);}
}

2、在将 TankMovement.cs 拖入到 Tank 上时,选择 Tank 的第一个 Audio Source Component 拖入到TankMovement 的 Movement Audio上,并选择 Engine Idling 为 EngineIdle 音频,Engine Drving 为 EngineDrving 音频,至此点击 Apply,将我们后面对 Tank 的修改保存到 Tank prefab 中

clipboard.png

3、保存场景,点击 Play 试玩一下

图片描述

通过今天的教程,你可以学会

  • 场景设置,基本的物体操作
  • 编程控制物体移动

下期教程继续。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/254345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Play框架的用户验证。

最近刚刚参与一个基于Play框架的管理平台的升级工作&#xff0c;其中涉及到了用户的验证工作。第一次接触play框架&#xff0c;直接看已有代码&#xff0c;有点晕。因此&#xff0c;自己实现了一个简单的用户验证功能。 首先&#xff0c;新建一个User类&#xff0c;包含两个属性…

C#条件运算符if-else的简化格式

文章目录博主写作不容易&#xff0c;孩子需要您鼓励 万水千山总是情 , 先点个赞行不行 条件运算符&#xff08;&#xff1f;&#xff1a;&#xff09;是&#xff49;&#xff46;……&#xff45;&#xff4c;&#xff53;&#xff45;的简化形式 其使用格式为&#xff1a…

码率控制方式选择

同码率下的图像质量或同图像质量下的码率。 AVCodecContext /** * the average bitrate * - encoding: Set by user; unused for constant quantizer encoding. * - decoding: Set by libavcodec. 0 or some bitrate if this info is available in the strea…

Fortran执行语句中的“双冒号” ::

双冒号“::”&#xff0c;通常出现于Fortran在变量声明中&#xff0c;但是在特殊情况下&#xff0c;也会出现于数组中。例如&#xff1a; ... real,target,dimension(10):: a real,pointer,dimension(:):: pa,pb integer:: n3 ... pa > a(n::1) pb > a(n:10:1) ... 咋一看…

VS配置本地IIS以域名访问

1.IIS下配置自己的网站&#xff0c;添加主机名 2.修改hosts文件&#xff08;C://Windows/System32/drivers/etc&#xff09; 3.VS中配置项目Web服务器&#xff08;选择外部主机&#xff09; 转载于:https://www.cnblogs.com/zuimeideshi520/p/7028544.html

try、catch、finally 和 throw-C#异常处理

文章目录博主写作不容易&#xff0c;孩子需要您鼓励 万水千山总是情 , 先点个赞行不行 异常是在程序执行期间出现的问题。C# 中的异常是对程序运行时出现的特殊情况的一种响应&#xff0c;比如尝试除以零。 异常提供了一种把程序控制权从某个部分转移到另一个部分的方式。…

Spark RDD/Core 编程 API入门系列 之rdd实战(rdd基本操作实战及transformation和action流程图)(源码)(三)...

本博文的主要内容是&#xff1a; 1、rdd基本操作实战 2、transformation和action流程图 3、典型的transformation和action RDD有3种操作&#xff1a; 1、 Trandformation 对数据状态的转换&#xff0c;即所谓算子的转换 2、 Action 触发作业&#xff0c;即所谓得结果…

用GDB调试程序

GDB概述GDB 是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许&#xff0c;各位比较喜欢那种图形界面方式的&#xff0c;像VC、BCB等IDE的调试&#xff0c;但如果你是在 UNIX平台下做软件&#xff0c;你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所…

灯塔的出现给那些有想法,有能力而又缺乏资金的社区人士提供了一条途径

2019独角兽企业重金招聘Python工程师标准>>> 在上个月&#xff0c;BCH社区传出基于比特币现金的众筹平台Lighthouse&#xff08;灯塔&#xff09;正在复活的消息&#xff0c;并且有网友在论坛上贴出了部分网站图片。当消息被证实为真&#xff0c;官网和项目的审核细…

PID 算法理解

PID 算法 使用环境&#xff1a;受到外界的影响不能按照理想状态发展。如小车的速度不稳定的调节&#xff0c;尽快达到目标速度。 条件&#xff1a;闭环系统->有反馈 要求&#xff1a;快准狠 分类&#xff1a;位置式、增量式 增量式 输入&#xff1a;前次速度、前前次速度、前…

C#字符串的基本操作

文章目录简介字符串判断是否相等语法实例字符串比较大小语法实例判断字符串变量是否包含指定字符或字符串语法实例查找字符串变量中指定字符或字符串出现的位置语法实例取子串语法实例插入子串语法实例删除子串语法实例替换子串语法实例去除字符串空格语法实例博主写作不容易&a…

C++利用SOCKET传送文件

C利用SOCKET传送文件 /*server.h*/ #pragma comment(lib, "WS2_32") #include <WinSock2.h> #include <iostream> //#include <stdio.h> #include <assert.h> #ifndef COMMONDEF_H #define COMMONDEF_H #define MAX_PACKET_SIZE 10240 …

三种方式在CentOS 7搭建KVM虚拟化平台

KVM 全称是基于内核的虚拟机&#xff08;Kernel-based Virtual Machine&#xff09;&#xff0c;它是一个 Linux的一个内核模块&#xff0c;该内核模块使得 Linux变成了一个Hypervisor&#xff1a;它由 Quramnet开发&#xff0c;该公司于 2008年被 Red Hat 收购 KVM的整体结构&…

(五)EasyUI使用——datagrid数据表格

DataGrid以表格形式展示数据&#xff0c;并提供了丰富的选择、排序、分组和编辑数据的功能支持。DataGrid的设计用于缩短开发时间&#xff0c;并且使开发人员不需要具备特定的知识。它是轻量级的且功能丰富。单元格合并、多列标题、冻结列和页脚只是其中的一小部分功能。具体功…

拾取模型的原理及其在THREE.JS中的代码实现

1. Three.js中的拾取 1.1. 从模型转到屏幕上的过程说开 由于图形显示的基本单位是三角形&#xff0c;那就先从一个三角形从世界坐标转到屏幕坐标说起&#xff0c;例如三角形abc 乘以模型视图矩阵就进入了视点坐标系&#xff0c;其实就是相机所在的坐标系&#xff0c;如下图&am…

StringBuilder-C#字符串对象

博主写作不容易&#xff0c;孩子需要您鼓励 万水千山总是情 , 先点个赞行不行 在C# 中&#xff0c;string是引用类型&#xff0c;每次改变string类对象的值&#xff0c;即修改字符串变量对应的字符串&#xff0c;都需要在内存中为新的字符串重新分配空间。在默写特定的情况…

java 19 - 11 异常的注意事项

1 /*2 * 异常注意事项:3 * A:子类重写父类方法时&#xff0c;子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)4 * B:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常5 * C:如果被重写的…

数组去重的各种方式对比

数组去重&#xff0c;是一个老生常谈的问题了&#xff0c;在各厂的面试中也会有所提及&#xff0c;接下来就来细数一下各种数组去重的方式吧&#xff1b; 对于以下各种方式都统一命名为 unique&#xff0c;公用代码如下&#xff1a; // 生成一个包含100000个[0,50000)随机数的数…

Linux平台Makefile文件的编写基础篇和GCC参数详解

问&#xff1a;gcc中的-I.是什么意思。。。。看到了有的是gcc -I. -I/usr/xxxxx..那个-I.是什么意思呢 最佳答案 答&#xff1a;-Ixxx 的意思是除了默认的头文件搜索路径(比如/usr/include等&#xff09;外&#xff0c;同时还在路径xxx下搜索需要被引用的头文件。 所以你的gcc …