Survival Shooter 学习


using UnityEngine;
using System.Collections;
namespace CompleteProject
{
/// <summary>
/// 摄像机跟随
/// </summary>
public class CameraFollow : MonoBehaviour
{
/// <summary>
/// 摄像机跟随的目标
/// </summary>
public Transform target;
/// <summary>
/// 相机的移动速度
/// </summary>
public float smoothing = 5f;
/// <summary>
/// 摄像机相对于目标的偏移
/// </summary>
Vector3 offset;
void Start ()
{
//计算偏移
offset = transform.position - target.position;
}
void FixedUpdate ()
{
//计算相机要移动到的位置
Vector3 targetCamPos = target.position + offset;
//移动相机
transform.position = Vector3.Lerp (transform.position, targetCamPos, smoothing * Time.deltaTime);
}
}
}
CameraFollow
using UnityEngine;
namespace CompleteProject
{
/// <summary>
/// 敌人管理
/// </summary>
public class EnemyManager : MonoBehaviour
{
/// <summary>
/// 玩家生命
/// </summary>
public PlayerHealth playerHealth;
/// <summary>
/// 敌人预设
/// </summary>
public GameObject enemy;
/// <summary>
/// 每次孵化敌人的间隔
/// </summary>
public float spawnTime = 3f;
/// <summary>
/// 孵化敌人的位置
/// </summary>
public Transform[] spawnPoints;
void Start ()
{
InvokeRepeating ("Spawn", spawnTime, spawnTime);
}
/// <summary>
/// 孵化敌人
/// </summary>
void Spawn ()
{
//如果玩家当前生命<=0,不处理
if(playerHealth.currentHealth <= 0f)
{
return;
}
//随机找一个孵化点
, spawnPoints.Length);
//在这个孵化点孵化敌人
Instantiate (enemy, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
}
}
}
EnemyManager
using UnityEngine;
using System.Collections;
namespace CompleteProject
{
/// <summary>
/// 玩家攻击
/// </summary>
public class EnemyAttack : MonoBehaviour
{
/// <summary>
/// 每次攻击的时间间隔
/// </summary>
public float timeBetweenAttacks = 0.5f;
/// <summary>
/// 每次攻击照成的伤害
/// </summary>
;
/// <summary>
/// 敌人Animator
/// </summary>
Animator anim;
/// <summary>
/// 玩家
/// </summary>
GameObject player;
/// <summary>
/// 玩家生命
/// </summary>
PlayerHealth playerHealth;
/// <summary>
/// 敌人生命
/// </summary>
EnemyHealth enemyHealth;
/// <summary>
/// 玩家是否在攻击范围内
/// </summary>
bool playerInRange;
/// <summary>
/// 下次攻击的计时器
/// </summary>
float timer;
void Awake ()
{
player = GameObject.FindGameObjectWithTag ("Player");
playerHealth = player.GetComponent <PlayerHealth> ();
enemyHealth = GetComponent<EnemyHealth>();
anim = GetComponent <Animator> ();
}
void OnTriggerEnter (Collider other)
{
//如果碰到玩家
if(other.gameObject == player)
{
//设置标志位为true
playerInRange = true;
}
}
void OnTriggerExit (Collider other)
{
//如果玩家离开
if(other.gameObject == player)
{
//设置标志位为false
playerInRange = false;
}
}
void Update ()
{
//每帧增加计时器的时间
timer += Time.deltaTime;
//当计时器的时间大于等于每次攻击的时间间隔
//玩家在攻击范围内
//敌人的当前血量大于0
)
{
//攻击
Attack ();
}
//如果玩家的生命值小于等于0
)
{
//animator触发PlayerDead动画
anim.SetTrigger ("PlayerDead");
}
}
/// <summary>
/// 攻击
/// </summary>
void Attack ()
{
//重置攻击计时器
timer = 0f;
//如果玩家当前生命大于0
)
{
//伤害玩家
playerHealth.TakeDamage (attackDamage);
}
}
}
}
EnemyAttack
using UnityEngine;
namespace CompleteProject
{
public class EnemyHealth : MonoBehaviour
{
/// <summary>
/// 敌人初始生命
/// </summary>
;
/// <summary>
/// 敌人当前生命
/// </summary>
public int currentHealth;
/// <summary>
/// 敌人死亡后下沉的速度
/// </summary>
public float sinkSpeed = 2.5f;
/// <summary>
/// 被玩家击杀时,玩家获得的得分
/// </summary>
;
/// <summary>
/// 死亡声音
/// </summary>
public AudioClip deathClip;
Animator anim;
AudioSource enemyAudio;
/// <summary>
/// 敌人受到伤害时的粒子系统
/// </summary>
ParticleSystem hitParticles;
CapsuleCollider capsuleCollider;
/// <summary>
/// 敌人是否死亡
/// </summary>
bool isDead;
/// <summary>
/// 敌人是否下沉
/// </summary>
bool isSinking;
void Awake ()
{
anim = GetComponent <Animator> ();
enemyAudio = GetComponent <AudioSource> ();
hitParticles = GetComponentInChildren <ParticleSystem> ();
capsuleCollider = GetComponent <CapsuleCollider> ();
//设置当前生命为初始生命
currentHealth = startingHealth;
}
void Update ()
{
//如果敌人在下沉
if(isSinking)
{
//移动敌人在y轴的位置
transform.Translate (-Vector3.up * sinkSpeed * Time.deltaTime);
}
}
/// <summary>
/// 受到伤害
/// </summary>
/// <param name="amount">伤害数值</param>
/// <param name="hitPoint">受到伤害的位置</param>
public void TakeDamage (int amount, Vector3 hitPoint)
{
//如果敌人死亡,不处理
if(isDead)
return;
//播放受伤声音
enemyAudio.Play ();
//减少当前血量
currentHealth -= amount;
//将受伤的粒子系统的位置设置为受到伤害的位置
hitParticles.transform.position = hitPoint;
//播放粒子系统
hitParticles.Play();
//如果当前血量<=0
)
{
//调用死亡函数
Death ();
}
}
/// <summary>
/// 死亡
/// </summary>
void Death ()
{
//修改死亡标志位
isDead = true;
//将碰撞器改为触发器
capsuleCollider.isTrigger = true;
//触发animator的dead动画
anim.SetTrigger ("Dead");
//播放敌人死亡声音
enemyAudio.clip = deathClip;
enemyAudio.Play ();
}
/// <summary>
/// 敌人开始下沉
/// </summary>
public void StartSinking ()
{
//关闭NavMeshAgent
GetComponent <NavMeshAgent> ().enabled = false;
//将Rigidbody设置为kinematic
GetComponent <Rigidbody> ().isKinematic = true;
//将下沉标志位设置为true
isSinking = true;
//添加玩家的得分
ScoreManager.score += scoreValue;
//销毁敌人
Destroy (gameObject, 2f);
}
}
}
EnemyHealth
using UnityEngine;
using System.Collections;
namespace CompleteProject
{
/// <summary>
/// 敌人移动
/// </summary>
public class EnemyMovement : MonoBehaviour
{
/// <summary>
/// 玩家的位置
/// </summary>
Transform player;
/// <summary>
/// 玩家的生命
/// </summary>
PlayerHealth playerHealth;
/// <summary>
/// 敌人生命
/// </summary>
EnemyHealth enemyHealth;
/// <summary>
/// NavMeshAgent
/// </summary>
NavMeshAgent nav;
void Awake ()
{
player = GameObject.FindGameObjectWithTag ("Player").transform;
playerHealth = player.GetComponent <PlayerHealth> ();
enemyHealth = GetComponent <EnemyHealth> ();
nav = GetComponent <NavMeshAgent> ();
}
void Update ()
{
//如果敌人生命和玩家生命都大于0
&& playerHealth.currentHealth > )
{
//敌人移动到玩家位置
nav.SetDestination (player.position);
}
//否则关闭NavMeshAgent
else
{
nav.enabled = false;
}
}
}
}
EnemyMovement
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.SceneManagement;
namespace CompleteProject
{
/// <summary>
/// 玩家生命
/// </summary>
public class PlayerHealth : MonoBehaviour
{
/// <summary>
/// 游戏开始时玩家的生命
/// </summary>
;
/// <summary>
/// 玩家的当前生命
/// </summary>
public int currentHealth;
/// <summary>
/// 生命滑动条
/// </summary>
public Slider healthSlider;
/// <summary>
/// 玩家受到伤害时的图片
/// </summary>
public Image damageImage;
/// <summary>
/// 玩家死亡的声音剪辑
/// </summary>
public AudioClip deathClip;
/// <summary>
/// 伤害图片变透明的速度
/// </summary>
public float flashSpeed = 5f;
/// <summary>
/// 伤害图片的颜色
/// </summary>
public Color flashColour = new Color(1f, 0f, 0f, 0.1f);
Animator anim;
AudioSource playerAudio;
PlayerMovement playerMovement;
PlayerShooting playerShooting;
/// <summary>
/// 玩家是否死亡
/// </summary>
bool isDead;
/// <summary>
/// 玩家是否受到伤害
/// </summary>
bool damaged;
void Awake ()
{
anim = GetComponent <Animator> ();
playerAudio = GetComponent <AudioSource> ();
playerMovement = GetComponent <PlayerMovement> ();
playerShooting = GetComponentInChildren <PlayerShooting> ();
//设置当前血量为起始血量
currentHealth = startingHealth;
}
void Update ()
{
//如果玩家受到伤害,修改伤害图片的颜色
if(damaged)
{
damageImage.color = flashColour;
}
//没有受到伤害,伤害图片渐隐
else
{
damageImage.color = Color.Lerp (damageImage.color, Color.clear, flashSpeed * Time.deltaTime);
}
//设置伤害标志位false
damaged = false;
}
/// <summary>
/// 玩家受到伤害
/// </summary>
/// <param name="amount">受到伤害的数值</param>
public void TakeDamage (int amount)
{
//设置伤害标志位true
damaged = true;
//减少当前血量
currentHealth -= amount;
//将当前血量应用到血量滑动条上
healthSlider.value = currentHealth;
//播放受伤的声音
playerAudio.Play ();
//如果当前血量<=0并且玩家死亡的标志位位true.
&& !isDead)
{
Death ();
}
}
/// <summary>
/// 玩家死亡
/// </summary>
void Death ()
{
//修改死亡标志位
isDead = true;
//关闭射击特效
playerShooting.DisableEffects ();
//触发死亡动画
anim.SetTrigger ("Die");
//播放死亡声音
playerAudio.clip = deathClip;
playerAudio.Play ();
//关闭移动和射击脚本
playerMovement.enabled = false;
playerShooting.enabled = false;
}
/// <summary>
/// 重新开始
/// </summary>
public void RestartLevel ()
{
//加载场景
SceneManager.LoadScene ();
}
}
}
PlayerHealth
using UnityEngine;
using UnitySampleAssets.CrossPlatformInput;
namespace CompleteProject
{
/// <summary>
/// 玩家移动
/// </summary>
public class PlayerMovement : MonoBehaviour
{
/// <summary>
/// 玩家移动速度
/// </summary>
public float speed = 6f;
/// <summary>
/// 玩家移动方向
/// </summary>
Vector3 movement;
/// <summary>
/// Animator
/// </summary>
Animator anim;
/// <summary>
/// Rigidbody
/// </summary>
Rigidbody playerRigidbody;
#if !MOBILE_INPUT
/// <summary>
/// 地面
/// </summary>
int floorMask;
/// <summary>
/// 射线的长度
/// </summary>
float camRayLength = 100f;
#endif
void Awake ()
{
#if !MOBILE_INPUT
floorMask = LayerMask.GetMask ("Floor");
#endif
anim = GetComponent <Animator> ();
playerRigidbody = GetComponent <Rigidbody> ();
}
void FixedUpdate ()
{
//获取水平和垂直的输入
float h = CrossPlatformInputManager.GetAxisRaw("Horizontal");
float v = CrossPlatformInputManager.GetAxisRaw("Vertical");
//处理玩家的移动
Move (h, v);
//处理玩家的旋转
Turning ();
//处理玩家的动画
Animating (h, v);
}
/// <summary>
/// 移动
/// </summary>
/// <param name="h"></param>
/// <param name="v"></param>
void Move (float h, float v)
{
movement.Set (h, 0f, v);
//设置移动速度
movement = movement.normalized * speed * Time.deltaTime;
//刚体移动
playerRigidbody.MovePosition (transform.position + movement);
}
/// <summary>
/// 旋转
/// </summary>
void Turning ()
{
#if !MOBILE_INPUT
//从鼠标点击的屏幕位置创建射线
Ray camRay = Camera.main.ScreenPointToRay (Input.mousePosition);
//接收射线撞击到地面的数据
RaycastHit floorHit;
//发射射线
if(Physics.Raycast (camRay, out floorHit, camRayLength, floorMask))
{
//创建一个玩家到撞击点的向量
Vector3 playerToMouse = floorHit.point - transform.position;
//保证这个向量的y为0
playerToMouse.y = 0f;
//根据这个向量创建四元数
Quaternion newRotatation = Quaternion.LookRotation (playerToMouse);
//刚体旋转
playerRigidbody.MoveRotation (newRotatation);
}
#else
Vector3 turnDir = new Vector3(CrossPlatformInputManager.GetAxisRaw("Mouse X") , 0f , CrossPlatformInputManager.GetAxisRaw("Mouse Y"));
if (turnDir != Vector3.zero)
{
Vector3 playerToMouse = (transform.position + turnDir) - transform.position;
playerToMouse.y = 0f;
Quaternion newRotatation = Quaternion.LookRotation(playerToMouse);
playerRigidbody.MoveRotation(newRotatation);
}
#endif
}
/// <summary>
/// 播放动画
/// </summary>
/// <param name="h">水平输入值</param>
/// <param name="v">垂直输入值</param>
void Animating (float h, float v)
{
bool walking = h != 0f || v != 0f;
anim.SetBool ("IsWalking", walking);
}
}
}
PlayerMovement
using UnityEngine;
using UnitySampleAssets.CrossPlatformInput;
namespace CompleteProject
{
/// <summary>
/// 玩家射击
/// </summary>
public class PlayerShooting : MonoBehaviour
{
/// <summary>
/// 没发子弹造成的伤害
/// </summary>
;
/// <summary>
/// 每发子弹的时间间隔
/// </summary>
public float timeBetweenBullets = 0.15f;
/// <summary>
/// 射击范围
/// </summary>
public float range = 100f;
/// <summary>
/// 发射子弹的计时器
/// </summary>
float timer;
/// <summary>
/// 射击射线
/// </summary>
Ray shootRay;
/// <summary>
/// 射击击中点
/// </summary>
RaycastHit shootHit;
/// <summary>
/// 可以受到射击的层
/// </summary>
int shootableMask;
/// <summary>
///
/// </summary>
ParticleSystem gunParticles;
/// <summary>
/// 枪的线条渲染器
/// </summary>
LineRenderer gunLine;
/// <summary>
/// 枪的声音
/// </summary>
AudioSource gunAudio;
/// <summary>
/// 枪的灯光
/// </summary>
Light gunLight;
/// <summary>
///
/// </summary>
public Light faceLight;
/// <summary>
/// 效果的显示时间
/// </summary>
float effectsDisplayTime = 0.2f;
void Awake ()
{
//获取可以射击的层
shootableMask = LayerMask.GetMask ("Shootable");
gunParticles = GetComponent<ParticleSystem> ();
gunLine = GetComponent <LineRenderer> ();
gunAudio = GetComponent<AudioSource> ();
gunLight = GetComponent<Light> ();
//faceLight = GetComponentInChildren<Light> ();
}
void Update ()
{
//每帧增加计时器的时间
timer += Time.deltaTime;
#if !MOBILE_INPUT
//如果按下发射按键,计时器大于两次发射子弹的间隔时,时间比例不等于0
)
{
//射击
Shoot ();
}
#else
|| CrossPlatformInputManager.GetAxisRaw() && timer >= timeBetweenBullets)
{
Shoot();
}
#endif
//如果计时器超过特效显示的时间
if(timer >= timeBetweenBullets * effectsDisplayTime)
{
//关闭射击效果
DisableEffects ();
}
}
public void DisableEffects ()
{
gunLine.enabled = false;
faceLight.enabled = false;
gunLight.enabled = false;
}
/// <summary>
/// 射击
/// </summary>
void Shoot ()
{
//重置计时器
timer = 0f;
//播放射击声音
gunAudio.Play ();
gunLight.enabled = true;
faceLight.enabled = true;
//先停止粒子特效,然后再播放特效
gunParticles.Stop ();
gunParticles.Play ();
//设置线条渲染器的第一个位置
gunLine.enabled = true;
gunLine.SetPosition (, transform.position);
//设置 射击射线的 起点和方向
shootRay.origin = transform.position;
shootRay.direction = transform.forward;
//发射射线,碰到敌人
if(Physics.Raycast (shootRay, out shootHit, range, shootableMask))
{
//敌人受到伤害
EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> ();
if(enemyHealth != null)
{
enemyHealth.TakeDamage (damagePerShot, shootHit.point);
}
//设置线条渲染器的第二个位置为射击点的位置
gunLine.SetPosition (, shootHit.point);
}
//没有碰到敌人,设置线条渲染器的第2个位置
else
{
gunLine.SetPosition (, shootRay.origin + shootRay.direction * range);
}
}
}
}
PlayerShooting
using UnityEngine;
namespace CompleteProject
{
/// <summary>
/// 游戏结束管理
/// </summary>
public class GameOverManager : MonoBehaviour
{
/// <summary>
/// 玩家生命
/// </summary>
public PlayerHealth playerHealth;
/// <summary>
/// Animator
/// </summary>
Animator anim;
void Awake ()
{
anim = GetComponent <Animator> ();
}
void Update ()
{
//如果玩家生命值小于等于0
)
{
//Animator设置GameOver触发器
anim.SetTrigger ("GameOver");
}
}
}
}
GameOverManager
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.Audio;
#if UNITY_EDITOR
using UnityEditor;
#endif
/// <summary>
/// 暂停管理
/// </summary>
public class PauseManager : MonoBehaviour {
public AudioMixerSnapshot paused;
public AudioMixerSnapshot unpaused;
/// <summary>
/// Canvas
/// </summary>
Canvas canvas;
void Start()
{
canvas = GetComponent<Canvas>();
}
void Update()
{
//按esc键 切换游戏状态
if (Input.GetKeyDown(KeyCode.Escape))
{
canvas.enabled = !canvas.enabled;
Pause();
}
}
/// <summary>
/// 暂停游戏
/// </summary>
public void Pause()
{
Time.timeScale = Time.timeScale == ? : ;
Lowpass ();
}
/// <summary>
/// 调整声音
/// </summary>
void Lowpass()
{
)
{
paused.TransitionTo(.01f);
}
else
{
unpaused.TransitionTo(.01f);
}
}
/// <summary>
/// 退出游戏
/// </summary>
public void Quit()
{
//调用编辑器的退出
#if UNITY_EDITOR
EditorApplication.isPlaying = false;
//调用正常的退出
#else
Application.Quit();
#endif
}
}
PauseManager
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
namespace CompleteProject
{
/// <summary>
/// 玩家分数管理
/// </summary>
public class ScoreManager : MonoBehaviour
{
/// <summary>
/// 玩家分数
/// </summary>
public static int score;
/// <summary>
/// 显示玩家分数的文本
/// </summary>
Text text;
void Awake ()
{
text = GetComponent <Text> ();
//重置玩家分数
score = ;
}
void Update ()
{
//更新玩家分数的显示
text.text = "Score: " + score;
}
}
}
ScoreManager
视频:https://pan.baidu.com/s/1geIxFs3
项目:https://pan.baidu.com/s/1gfDonkf
Survival Shooter 学习的更多相关文章
- JSBinding + SharpKit / 实战:转换 Survival Shooter
从 asset store 下载 Survival Shooter (商店里有2个版本,一种是给Unity5用的,一个是给Unity4.6用的,我们这个实验用的是后者,版本是2.2.如果) 1 删除多 ...
- Space Shooter 学习
using UnityEngine; using System.Collections; /// <summary> /// 背景滚动 /// </summary> publi ...
- Unity3D项目之 Survival Shooter 记录
1.导入资源 2.把预设文件的环境拖到场景中, 3.位置归0 4.保存场景 5.删除默认灯光,把预设灯光拖到场景中,位置归0 6.新建一个 Quad 7.旋转90度,设置缩放100,100,1 重命名 ...
- 【Unity3D】资源对象、预设、查找对象、组合模式等知识点
1.解释对象与资源区别于联系,根据官方案例,分别总结资源和对象组织的规则/规律. 下载并查看了Adam和Survival Shooter tutorial两个官方资源案例,这些案例作为资源,可以 ...
- UGUI全面实践教程
UGUI全面实践教程 试读文档下载地址:http://pan.baidu.com/s/1hq3UYGk 介绍:UGUI是Unity官方推出的最新UI系统.本教程为国内唯一的UGUI专向资料.本教程 ...
- apex-utility-ai-unity-survival-shooter
The AI has the following actions available: Action Function Shoot Fires the Kalashnikov Reload Reloa ...
- Unity代码热更新方案 JSBinding + SharpKit 首页
目前Unity的代码更新方案有很多,主要以lua为主. JSBinding + SharpKit 是一种新的技术,他做了两件事情: JSBinding将C#导出到 JavaScript (引擎是 Mo ...
- unity学习笔记1--Space Shooter
其实我一直觉得我是个模棱两可的人,就计算机这块来说,自己还是想制作游戏什么的,但是又得考虑到现实就业的问题,所以现在自己主要在学安卓和javaweb.现在大概是心血来潮吧,突然想追逐下自己的理想,虽然 ...
- R语言学习路线和常用数据挖掘包(转)
对于初学R语言的人,最常见的方式是:遇到不会的地方,就跑到论坛上吼一嗓子,然后欣然or悲伤的离去,一直到遇到下一个问题再回来.当然,这不是最好的学习方式,最好的方式是——看书.目前,市面上介绍R语言的 ...
随机推荐
- 5.4 C++重载输入与输出操作符
参考:http://www.weixueyuan.net/view/6382.html 总结: 在C++中,系统已经对左移操作符“<<”和右移操作符“>>”分别进行了重载,使其 ...
- 利用include动作实现参数传递
<%--程序string.jsp--%> <%@ page language="java" import="java.util.*" page ...
- Eclipse快捷键+遇到补充
MyEclipse 快捷键1(CTRL) Ctrl+1 快速修复Ctrl+D: 删除当前行Ctrl+Q 定位到最后编辑的地方Ctrl+L 定位在某行Ctrl+O 快速显示 OutLineCtrl+T ...
- FCC JS基础算法题(8):Slasher Flick(截断数组)
题目描述: 返回一个数组被截断n个元素后还剩余的元素,截断从索引0开始. 这个题目有两个方法,都比较简单,用slice方法: function slasher(arr, howMany) { // 请 ...
- LeetCode--1、26、27、35、53 Array(Easy)
1. Two Sum Given an array of integers, return indices of the two numbers such that they add up to ...
- Ubuntu16.04 执行sudo apt-get update出现E: Sub-process returned an error code错误
Reading package lists... Done E: Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr ...
- JSON的学习,希望可以指导
1.JSON的介绍 是一种轻量级的数据交换格式.简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言. 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率. 2.格式 JSON ...
- 拿到iframe页面里面的变量及元素的方法
先严重差评一下,用这种方法window.parent.document.frames['layui-layer-iframe1']不行!而且frames方法存在浏览器不兼容问题(貌似火狐不行) 页面d ...
- ubuntu + samba 共享失败
主机版本:ubuntu14.04 问题描述:Samba服务配置后仍然不通. samba服务这么成熟的东西,本以为在ubuntu上修改下smb.conf重启就得了,但是访问还是失败. 表现是,可以看到s ...
- NUCLEO-F767ZI评测 NUCLEO-F767ZI入门教程CubeMX
评测:http://www.21ic.com/eva/MCU/201606/679904.htm 入门教程