单页网站的制作企业网站排名优化方案
每日一句:保持热爱,奔赴下一场山海,愿大学生活,光芒万丈、快乐昂扬
目录
物理引擎
刚体Rigidbodyˈrɪdʒɪd/
碰撞器collider/kəˈlaɪdə(r)/
碰撞条件
碰撞三阶段
触发器
触发条件
触发三阶段
如果物体移动速度过快,碰撞检测失效—>解决方案:
开始时,使用射线检测
武器模块
枪
策划
需求分析
子弹
敌人子弹
物理引擎
模拟真实世界中物体特性的引擎
刚体Rigidbodyˈrɪdʒɪd/
·带有刚体组件的游戏物体
刚体组件可使游戏对象受物理引擎控制,在受到外力时,产生真实世界中的运动(重力、弹力、摩擦力)
碰撞器collider/kəˈlaɪdə(r)/
物理材质
·用于调整碰撞对象的摩擦力和反弹效果
project—>(右键)Physic Material/məˈtɪəriəl/
属性:
动态摩擦力Dynamic Friction/daɪˈnæmɪk ˈfrɪkʃn/ 静态摩擦力Static Friction
弹力Bounciness
摩擦力合并模式Friction Conbine Mode
合并反弹 Bounce/baʊns/ Combine/kəmˈbaɪn/
平均值Average/ˈævərɪdʒ/ 最小Min 最大Max 相乘Multipy
碰撞条件
·两者都具有碰撞器组件
·运动的物体具有刚体组件
碰撞三阶段
进入碰撞时执行(接触的第一帧执行)
void OnCollisionEnter(Collision/kəˈlɪʒ(ə)n/ collother)
碰撞体与刚体接触时,每帧执行
void OnCollisionStay(Collision collother)
停止碰撞时执行
void OnCollisionExit(Collision collother)
private void OnCollisionEnter(Collision collother)
{ // collother:获取对方碰撞器组件
collother.collider.GetComponent< >
//获取第一个接触点
ContactPoint/ˈkɒntækt/ cp=collother.contacts[0];
//cp.point接触点的世界坐标
//cp.normal接触面法线
}
触发器
·碰撞器组件(collider),且Is Trigger属性被勾选的物体
现象:无碰撞效果
触发条件
·两者都具有碰撞组件
·其中一个带有刚体组件
·其中一个勾选Is Trigger
触发三阶段
当碰撞体进入触发器时执行
void OnTriggerEnter(Collider cldother)
当碰撞体与触发器接触时执行
void OnTriggerStay(Collider cldother)
当停止触发时执行
void OnTriggerExit(Collider cldother)
private void OnTriggerEnter(Collider collother)
{ // collother:就是对方碰撞器组件
collother.GetComponent< >
}
如果物体移动速度过快,碰撞检测失效—>解决方案:
开始时,使用射线检测
private void Start()
{
RaycastHit hit;
//重载15Raycast(起点坐标,方向,受击物体信息,距离,检测的层)
if(physics.Raycast(this.transform.position,this.transform.forward,out hit,100,mask))
{//检测到物体
targetPos=hit.point;//击中的位置
}
else
{//没有检测到物体
targetPos=this.transform.position+this.transform.forward*100;//物体正前方100米
}
}
void Update()
{ this.transform.position=
Vector3.MoveTowards(this.transform.position,targetPos,Time.deltaTime*100);
if((this.transform.position-targetPos).sqrMagnitude/ˈmæɡnɪtjuːd/<0.1f)
{print(“接触目标点”);
Destory(this.gameObject);//销毁子弹
}
武器模块
枪
策划
·如果弹匣内装有子弹,可以发射;否则等待更换弹匣
·发射子弹时,播放音效、动画、显示火花
·玩家的枪可以单发或连发
需求分析
·创建脚本—枪Gun,提供开火,更换弹匣功能
·创建脚本—单发枪SingleGun,继承自Gun,根据玩家输入调用相应(开关、更换弹匣)方法
·创建脚本—连发枪AutomaticGun,继承自Gun
子弹
策划
主角子弹
·根据击中敌人的部位减血
·子弹飞行到目标点销毁,并创建相应特效
敌人子弹
·击中玩家后减血
·子弹飞行到目标点销毁,并创建相应特效
·朝向玩家头部发射,飞行速度较慢,便于玩家躲避
需求分析:
·创建脚本—子弹Bullet,计算攻击的目标点,执行移动,创建接触特效
·创建脚本—玩家子弹PlayerBullet,继承自Bullet,根据击中敌人部位减血
·创建脚本—敌人子弹EnemyBullet,继承自Bullet,根据击中玩家后减血
EnemyAI类(续)
private Gun gun;
private void Start()
{gun=GetComponentInChildren<Gun>();}
Attack()
public float delay;
motor.LookRotation(playerStatusInfo.Instance.headTF.position);
if(atkTimer<=Time.time)
{Invoke(“Shoot”,delay);}
private void Shoot()
{{//发射子弹(建议使用动画事件替代)
//发起攻击(从枪口位置指向玩家头部位置)
gun.Firing(playerStatusInfo.Instance.headTF.position-gun.firePointTF,position);
EnemyMotor类(续)
public void LookRotation(Vector3 targetPoint)
{//当前物体注视目标点旋转
this.transform.LookAt(targetPoint);//会出现头部高于自身物体 人物倾斜,旋转速度过快,解决—>
targetPoint.y=this.transform.position.y;
或
Quaternion dir = Quaternion.LookRotation(targetPoint - this.transform.position);
Quaternion rotate = Quaternion.Lerp(this.transform.rotation, dir, 20 * Time.deltaTime);
Vector3 euler = rotate.eulerAngles;
//仅仅沿Y轴旋转
this.transform.eulerAngles = new Vector3(0, euler.y, 0);
上波代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{ [HideInInspector]public float atk;/// <summary>/// 攻击距离/// </summary>public float attackDistance = 20;/// <summary>/// 射线检测层/// </summary>public LayerMask mask;protected RaycastHit hit;//受击目标信息private Vector3 targetPos;/// <summary>/// 移动速度/// </summary>public float moveSpeed=200;//计算目标点private void CalculateTargetPoint(){//当前位置(枪口位置,当前方向(枪口方向),受击目标信息,攻击最大距离,射线检测层)if (Physics.Raycast(this.transform.position, this.transform.forward, out hit, attackDistance, mask))targetPos = hit.point;elsetargetPos = this.transform.position + this.transform.forward * attackDistance;}//移动private void Movement(){this.transform.position = Vector3.MoveTowards(this.transform.position, targetPos, moveSpeed * Time.deltaTime);}//到达目标点;销毁,创建相关特效//根据目标点物体的标签hit.collider.tag创建特效private void Awake(){CalculateTargetPoint();}// Update is called once per framevoid Update(){Movement();//如果到达目标点if((this.transform.position-targetPos).sqrMagnitude<0.1f){Destroy(this.gameObject);GenerateContactEffect();}}/// <summary>/// 生成特效/// </summary>private void GenerateContactEffect(){if (hit.collider == null) return;//根据目标物体标签创建相应特效//switch(hit.collider.tag)【弊端】每次增加标签都得创建代码//{// case "":// break;//}//特效名称:存放路径+接触物体标签//资源较多,通过代码读取资源(用Recources读取,资源必须放到Recources目录下)//根据标签加载资源(消耗性能)【建议使用对象池替代】GameObject prefabGo = Recources.Load<GameObject>("目录/"+hit.collider.tag);if(prefabGo)//创建资源(资源预设体,目标点位置向法线方向移动0.01米,z轴朝向法线方向)Instantiate(prefabGo,targetPos+hit.normal*0.01f,Quaternion.LookRotation(hit.normal));}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 玩家状态信息类
/// </summary>
public class playerStatusInfo : MonoBehaviour
{public static playerStatusInfo Instance { get; private set; }private void Awake(){Instance = this;//把当前对象的引用放进来}public float HP = 1000;public float maxHP = 1000;public Transform headTF;//玩家头部位置变换public void Damage(float amount){HP -= amount;if(HP<=0){Death();}}public void Death(){//游戏结束}// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnemyBullet :Bullet
{// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}private void OnTriggerEnter(Collider other){//如果与玩家接触if(other.tag=="标签"){//玩家减血//调用玩家的受伤方法,把攻击力传进去playerStatusInfo.Instance.Damage(atk);//销毁子弹Destroy(this.gameObject);}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class playerBullet : Bullet
{//根据敌人部位减血(希望到达物体上再减血,需要使用委托)// Start is called before the first frame updatevoid Start(){float atk = CalculateAttackForce();//base.hit.collider.name;//击中敌人部位的名称if(hit.collider!=null&&hit.collider.tag=="Enemy")hit.collider.GetComponentInParent<EnemyStatusInfo>().Damage(atk);}// Update is called once per framevoid Update(){}//计算攻击力private float CalculateAttackForce(){//【建议】使用配置文件替换//根据受击物体部位名称switch(hit.collider.name){case "脑袋名称"://击中头部return atk * 3;case "身体名称":return atk * 1.5f;default:return atk;}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[RequireComponent(typeof(AudioSource))]
public class Gun : MonoBehaviour
{/// <summary>/// 攻击力/// </summary>public float atk = 100;public GameObject BulletPrefab;//需要发射的子弹预设体private AudioSource audioSaurce;//声音源public AudioClip clip;//发射子弹时的音频片段private GunAnimation anim;private MuzzleFlash muzzleFlash;protected virtual void Start(){anim = GetComponent<GunAnimation>();}// Update is called once per framevoid Update(){}/// <summary>/// 开火/// </summary>/// <param name="direction">子弹朝向</param>public void Firing(Vector3 direction){//玩家枪发射:枪口方向//敌人发射:从枪口位置朝向玩家头部位置//如果敌人枪没有动画,则不调用准备子弹方法,如果准备子弹失败if (anim!=null&&Ready() == false) return;//判断弹匣内是否包含子弹//发射子弹//播放音频、动画audioSaurce.PlayOneShot(clip);if(anim)anim.action.Play(anim.fireAnimName);muzzleFlash.DisplayFlash();//创建子弹(instantiate创建出来的是Object转换成GameObject)GameObject bulletgo=Instantiate(BulletPrefab, firePoint.position, Quaternion.LookRotation(direction))as GameObject;//传递信息bulletgo.GetComponent<Bullet>().atk = atk;}/// <summary>/// 准备子弹/// </summary>/// <returns></returns>private bool Ready(){//如果弹匣内没有子弹或更换弹匣动画正在播放if (currentAmmoNullets <= 0 || anim.action.Isplaying(anim.UpdateAmmoAnimeName))return false;//减少弹匣内子弹数currentAmmoNullets--;//如果缺少子弹播放缺少子弹动画if (currentAmmoNullets == 0)anim.action.play(anim.lackBulletAnimeName);return true;}public int ammolapacity = 15;//弹匣容量public int currentAmmoNullets = 15;当前弹匣内子弹数(15)public int ramainBullets = 90;//剩余总子弹数(90)/// <summary>/// 更换弹匣/// </summary>public void UpdateAmmeo(){}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class AutomaticGun : Gun
{// Start is called before the first frame updateprotected override void Start(){base.Start();//子类做的事}// Update is called once per framevoid Update(){}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SingleGun : Gun
{private Transform firePoint;// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){if(Input.GetMouseButtonDown(0)){base.Firing(firePoint);}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 枪动画
/// </summary>
public class GunAnimation : MonoBehaviour
{//开枪动画public string fireAnimName = "fire";//更换弹匣动画public string UpdateAmmoAnimeName = "updateAmmo";//缺少子弹动画public string lackBulletAnimeName = "lackBullet";public AnimationAction action;private void Awake(){//动画组件在孩子身上,怎么找呢?——>action = new AnimationAction(GetComponentInChildren<Animation>());}
}