枪支射击
1.搭建基本场景。
相关代码:
//登录
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class id : MonoBehaviour
{
public InputField inputid; //账号
public InputField inputpassword; //密码
public Text t; //返回文本
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void idpassword()
{
if (inputid.text == "shoot" && inputpassword.text == "123456")
{
SceneManager.LoadScene("start"); //输入正确,跳转到开始界面
}
else
{
t.text = "账号或密码错误";
t.color = Color.red; //输入错误,继续保持此界面
}
}
}
//进度条
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Load : MonoBehaviour {
private AsyncOperation aync;
public Image load; //进度条
private int figure = 0; //已加载的进度
public Text loadtext; //百分制显示进度数值
// Use this for initialization
void Start () {
//开启一个协程,它会根据迭代器中yield return 来判断什么时候暂时退出当前函数
//然后在下一段时间继续执行yield return 后面的函数代码
//会在第一次运行后一直执行,直到有代码控制它停止
StartCoroutine("LoadScence");
}
IEnumerator LoadScence() //定义一个迭代器,每一帧返回一次当前的载入进度,同时关闭自动的场景跳转
{
aync = SceneManager.LoadSceneAsync("shoot"); //要跳转的场景
aync.allowSceneActivation = false;
yield return aync;
}
// Update is called once per frame
void Update () {
if (aync == null) //判断是否有场景正在加载
{
return;
}
int progrssvalue = 0; //百分制进度
//当场景加载进度在90%以下时,将数值以整数百分制呈现,当资源加载到90%时就将百分制进度设置为100
if (aync.progress < 0.9f)
{
progrssvalue = (int)aync.progress * 100;
}
else
{
progrssvalue = 100;
}
//对进度条和百分制数据进行更改,已加载进度与百分制进度比较
if (figure < progrssvalue)
{
figure++;
load.fillAmount = figure / 100f; //进度条与已加载进度数值保持一致
loadtext.text = "加载资源中:" +figure.ToString() + "%";
}
//一旦进度到达100时,开启自动场景跳转,LoadSceneAsync会加载完剩下的10%的场景资源
//LoadSceneAsync只能加载90%的场景资源,剩下的10%场景资源要在开启自动场景跳转后才加载
if (figure == 100)
{
aync.allowSceneActivation = true;
}
}
}
//继续,重玩,退出
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Vtime : MonoBehaviour
{
//时间对场景中所有物体生效,可赋给任一物体
public Button go; //继续
public Button replay; //重玩
public Button exit; //退出
// Use this for initialization
void Start()
{
Time.timeScale = 1; //一开始时间正常流逝
go.gameObject.SetActive(false); //隐藏
replay.gameObject.SetActive(false);
exit.gameObject.SetActive(false);
go.onClick.AddListener(VClick); //点击 继续 按钮时,执行函数(游戏继续,时间正常流逝,提示框消失)
}
public void VClick()
{
Cursor.visible = false; //隐藏鼠标
Time.timeScale = 1; //时间正常流逝(大于1,时间飞逝,小于1,时间减缓)
go.gameObject.SetActive(false);
replay.gameObject.SetActive(false);
exit.gameObject.SetActive(false);
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
Cursor.visible = true; //出现鼠标
Time.timeScale = 0; //时间暂停
go.gameObject.SetActive(true); //出现
replay.gameObject.SetActive(true);
exit.gameObject.SetActive(true);
}
}
}
//场景转换
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Scene : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void tranid()
{
SceneManager.LoadScene("id");
}
public void transhoot()
{
SceneManager.LoadScene("shoot");
}
public void tranload()
{
SceneManager.LoadScene("load");
}
}
2.开枪射击
鼠标左键按下开火,右键调出十字瞄准器,Q键改变枪支。
相关代码:
//切换枪支,枪支动画效果,生成子弹
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ShootBirth : MonoBehaviour
{
public Transform taget; //子弹发射口
RaycastHit raycastHit; //存储发射射线后产生的碰撞信息
public Camera cam;
Animator animator;
public int i=3; //步枪(m24)剩余子弹数
public Text text; //剩余子弹提示
public GameObject vM24; //可连发3颗子弹后再装膛
public GameObject v98k; //射击一次,装膛一次
bool isbool = true; //作为切换枪的条件
public PlayerRotation player; //可调用PlayerRotation脚本
// Use this for initialization
void Start()
{
Cursor.visible = false; //隐藏鼠标
animator = vM24.GetComponent<Animator>(); //一开始为步枪(m24)
}
// Update is called once per frame
void Update()
{
//步枪时(m24),true,狙击枪时(98k),false
if (Input.GetKeyDown(KeyCode.Q))
{
if (isbool)
{
v98k.SetActive(true);
vM24.SetActive(false);
animator = v98k.GetComponent<Animator>();
text.gameObject.SetActive(false); //剩余子弹数不需要显示
}
else
{
v98k.SetActive(false);
vM24.SetActive(true);
animator = vM24.GetComponent<Animator>();
text.gameObject.SetActive(true);
}
isbool = !isbool; //转化枪
player.Close(); //转换枪时,瞄准器会消失
player.isbool = true; //true状态,点击右键时会出现
}
text.text = "剩余子弹数:" + i;
//检查当前动画控制器所播放的动画片段
//获取动画控制器
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
//如果当前状态机所播放的动画片段是Idle
if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.Idle"))
{
if (Input.GetMouseButtonDown(0))
{
if (isbool) //为步枪状态时(m24),子弹数才减少
{
i = i - 1;
}
animator.SetInteger("shoot", 1);
Sources.instance.Playaudioclip("Sniper_Shoot");
//对子弹实例化,赋予和taget一样的位置和角度作为初始值(即在taget处发射子弹)
GameObject bullet = Instantiate(Resources.Load<GameObject>("zidan"), taget.position, taget.rotation);
Vector3 hitpoint; //触碰点
//从屏幕中间位置发射一条射线
Ray ray = cam.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));
//检测射线是否触碰到物体
if (Physics.Raycast(ray, out raycastHit)) //发射一条射线,和物体发生碰撞,碰撞后得到碰撞信息,返回true
{
//获取射线与物体触碰的点
hitpoint = raycastHit.point;
//使生成的子弹看向触碰点(向触碰点瞄准发射)
bullet.transform.LookAt(hitpoint);
//子弹发射口射线路径
Debug.DrawLine(taget.position, hitpoint, Color.red, 3); //起点,终点,颜色,时间
//瞄准点射线路径
Debug.DrawLine(cam.transform.position, hitpoint, Color.green, 3);
}
Destroy(bullet, 3);
}
}
if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.Shoot"))
{
if (isbool) //步枪状态(m24),可连续射击
{
if (i == 0) //无子弹时
{
animator.SetInteger("shoot", 2);
}
if (i > 0) //有子弹时
{
animator.SetInteger("shoot", 0);
}
}
else //狙击枪状态(98k),射击一次后立即装膛
{
animator.SetInteger("shoot", 2);
}
}
if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.Bolt"))
{
animator.SetInteger("shoot", 0);
player.Close(); //装膛时瞄准器关闭
player.isbool = true; //true状态,点击右键时会出现
Sources.instance.Playaudioclip("Sniper_Bolt");
if (isbool) //为步枪状态时(m24),装膛后子弹装满
{
i = 3;
}
}
}
}
//子弹移动,攻击敌人
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Bulletmove : MonoBehaviour {
// Use this for initialization
void Start () {
//给物体一个向前的速度(赋给子弹,将子弹转为预制体)
GetComponent<Rigidbody>().velocity = transform.forward * 10;
}
private void OnCollisionStay(Collision collision)
{
if (collision.gameObject.tag == "bear") //如果标签为bear
{
Destroy(gameObject); //子弹消失
collision.gameObject.GetComponent<BearHP>().xuetiao -= 30; //血量减少30
}
}
// Update is called once per frame
void Update ()
{
Destroy(gameObject, 3); //一段时间后消失
}
}
//音效
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sources : MonoBehaviour {
//一个播放器多个音效
public static Sources instance; //可在其他脚本中调用
public AudioSource audioSource; //播放器
public AudioClip[] audioClips; //音效
Dictionary<string, AudioClip> dictionary = new Dictionary<string, AudioClip>();
// Use this for initialization
void Start () {
instance = this;
foreach (AudioClip clip in audioClips)
{
dictionary.Add(clip.name, clip); //将所有名字和音效添加到字典
}
}
public void Playaudioclip(string audioname) //播放音效
{
if (dictionary.ContainsKey(audioname)) //判断字典中的key值是否包含所用音效
{
AudioClip clip = dictionary[audioname];
audioSource.clip = clip; //若包含则播放此音效
audioSource.Play();
}
}
// Update is called once per frame
void Update () {
}
}
3.人物的行走
玩家在自己的坐标空间内向WSAD移动,接触地面可按空格实现跳跃效果。
相关代码:
//人物移动,跳跃
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Playermove : MonoBehaviour {
//WSAD人物移动,空格跳跃
public float speed = 6f;
public float distance = 3.2f; //射线最大距离(值由物体距离决定,高一点即可)
public AudioSource music; //播放器
public AudioClip walk; //走路音效
// Use this for initialization
void Start () {
music = GetComponent<AudioSource>(); //获取播放器
}
//地面检测
bool Isground()
{
//以当前物体的中心点为起点,向下发射一条长度为distance的射线,检测是否触碰到碰撞盒(地面),触碰到则为true
return Physics.Raycast(transform.position, Vector3.down, distance);
}
// Update is called once per frame
void Update () {
float x = Input.GetAxis("Horizontal"); //AD移动
float y = Input.GetAxis("Vertical"); //WS移动
//Sources.instance.Playaudioclip("walk");
if (Input.GetButtonDown("Vertical"))
{
music.clip = walk; //设置音源
music.loop = true; //循环播放
music.Play(); //播放音源
}
if (Input.GetButtonUp("Vertical"))
{
music.Pause(); //暂停音频
}
//人物位移
transform.Translate(new Vector3(x, 0, y) * Time.deltaTime * speed, Space.Self); //以自身坐标为轴
if (Input.GetButtonDown("Jump")) //空格跳跃
{
if (Isground()) //返回值为true时
{
GetComponent<Rigidbody>().velocity = transform.up * speed; //可向上跳跃(加刚体)
}
}
}
}
4.枪的上下左右移动
移动鼠标,实现上下左右移动,抬头低头设置一个范围。
相关代码:
//旋转
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerRotation : MonoBehaviour {
//鼠标上下左右滑动,控制视角旋转
public float speed = 6f;
public Camera cam;
float x;
float y;
public GameObject obj; //瞄准镜
public bool isbool = true;
// Use this for initialization
void Start () {
x = cam.transform.eulerAngles.x;
}
// Update is called once per frame
void Update () {
y = Input.GetAxis("Mouse X") * speed; //人物y轴变化量(鼠标左右滑动)
x -= Input.GetAxis("Mouse Y") * speed; //摄像机上下旋转(鼠标上下滑动)
x = Mathf.Clamp(x, -20, 22); //旋转范围
cam.transform.eulerAngles = new Vector3(x, cam.transform.eulerAngles.y, 0); //摄像机变化值(欧拉角)
transform.localRotation = transform.localRotation * Quaternion.Euler(0, y, 0); //人物左右旋转(以y轴为中心旋转)
if (Input.GetMouseButtonDown(1)) //按鼠标右键进行瞄准器的切换
{
if (isbool)
{
obj.SetActive(true);
cam.fieldOfView = 20; //显示范围
//摄像机不渲染第8层(在右上角Layer中可知第几层)
cam.cullingMask = ~(1 << 8);
}
else
{
Close();
}
isbool = !isbool;
}
}
public void Close() //关闭瞄准镜
{
obj.SetActive(false);
cam.fieldOfView = 60;
cam.cullingMask = -1; //都显示
}
}
5.敌人
设定敌人生命值,受到攻击后减少,直至死亡,敌人死亡后,刷新生成,巡逻效果。
相关代码:
//巡逻
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Bearnav : MonoBehaviour {
//地面定为静态Static(右上角),Window-Navigation-Bake,烘焙地面
private NavMeshAgent meshAgent; //给追随物体添加组件
public Transform[] transforms; //为多个目标点建立数组
float time = 0;
int i = 0; //计目标点个数
public Animator animator;
// Use this for initialization
void Start()
{
meshAgent = GetComponent<NavMeshAgent>();
animator.SetBool("move", true);
meshAgent.SetDestination(transforms[0].position); //一开始去第一个目标点
}
private void OnCollisionStay(Collision collision)
{
if (collision.gameObject.tag == "Player")
{
animator.SetBool("attack", true);
}
}
private void OnCollisionExit(Collision collision)
{
if (collision.gameObject.tag == "Player")
{
animator.SetBool("attack", false);
}
}
// Update is called once per frame
void Update () {
if (Vector3.Distance(meshAgent.nextPosition, meshAgent.destination) < 2f) //下一步的位置与目标点位置相近,即到达
{
animator.SetBool("move", false);
time += Time.deltaTime; //3s时间内等待
if (time > 3) //到达3s后,去下一个目标点
{
//随机移动
i = Random.Range(0, transforms.Length - 1);
time = 0;
meshAgent.SetDestination(transforms[i].position); //下一个目标点的位置
animator.SetBool("move", true); //移动到下一个目标点
}
}
}
}
//血量
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BearHP : MonoBehaviour {
public Text text;
public float xuetiao = 100; //血条数值
public Image green; //血条绿值
public Image red;
public Transform taget; //敌人出现处
public GameObject[] Enemys;
// Use this for initialization
void Start () {
}
public void _Enemy() //生成敌人
{
GameObject bullet = Instantiate(Resources.Load<GameObject>("Bear"), taget.position, taget.rotation);
bullet.gameObject.SetActive(true);
text.gameObject.SetActive(true);
green.gameObject.SetActive(true);
red.gameObject.SetActive(true);
}
// Update is called once per frame
void Update()
{
if (xuetiao <= 30)
{
xuetiao = 0; //每次减少30的血值,如果不足30,置为0,防止变成负数
Destroy(gameObject); //血值为0,消失
text.gameObject.SetActive(false);
green.gameObject.SetActive(false);
red.gameObject.SetActive(false);
_Enemy();
xuetiao = 100;
}
green.fillAmount = xuetiao / 100; //血值绿条与血值数值相对应
text.text = "敌剩余血量:" + xuetiao; //在界面上显示血值
}
}