国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

事業(yè)單位網(wǎng)站開發(fā)工作規(guī)程網(wǎng)站優(yōu)化seo方案

事業(yè)單位網(wǎng)站開發(fā)工作規(guī)程,網(wǎng)站優(yōu)化seo方案,wordpress 手機端模板,網(wǎng)頁網(wǎng)站導讀怎么做上期將基礎的移動系統(tǒng)搭建完畢后就可以開始搭建更加復雜的系統(tǒng)部分了 前排提示,由于一開始僅思考如何完成操作相關功能,以至于到后面重構(gòu)稍微有些困難,繼續(xù)寫下去恐成屎山,故在搭完射擊和武器UI后不再繼續(xù)泛化到敵人和敵人狀態(tài)機…

上期將基礎的移動系統(tǒng)搭建完畢后就可以開始搭建更加復雜的系統(tǒng)部分了

前排提示,由于一開始僅思考如何完成操作相關功能,以至于到后面重構(gòu)稍微有些困難,繼續(xù)寫下去恐成屎山,故在搭完射擊和武器UI后不再繼續(xù)泛化到敵人和敵人狀態(tài)機

本次主要完成了

自由配置武器參數(shù):武器所需的所有參數(shù)都可進行調(diào)整

請?zhí)砑訄D片描述

武器的追隨準星:

根據(jù)輸入的武器槽位自動平滑的跟隨指定武器的槍線,換彈時也會有相應提示

在這里插入圖片描述

武器的切換:

不同武器根據(jù)數(shù)字鍵進行切換,在UI和準星上也會有所體現(xiàn)

在這里插入圖片描述

第一第三人稱的切換:

可以在第一第三人稱間無縫切換

在這里插入圖片描述

請看VCR!

Unity機甲2

文章目錄

    • 總覽
    • 武器系統(tǒng)
    • 子彈
    • 第一第三人稱轉(zhuǎn)換
    • UI

總覽

類圖結(jié)構(gòu)

請?zhí)砑訄D片描述

武器系統(tǒng)

武器使用狀態(tài)機進行實現(xiàn),WeaponState繼承自State,內(nèi)部持有Weapon的引用

Weapon是掛載在玩家身上的主要類,一個武器對應一個Weapon,手動輸入索引標識其所屬的武器槽位

public class Weapon : MonoBehaviour
{public enum FireMode{Single,Brust,Auto}private Entity owner;public int weaponSelectIndex = 0;public bool selected { get; private set; } = false;[Header("武器性能")][SerializeField] private int maxAmmo = 1;                                //最大彈匣彈藥量[SerializeField] private int maxPrepareAmmo = 16;                //最大后備彈藥量[SerializeField] private float shootingInterval = 0.1f;            //射擊間隔[SerializeField] public float reloadTime = 2;                            //換彈時間[Header("開火模式")][SerializeField] public FireMode fireMode = FireMode.Single;      //開火模式 [SerializeField] private int brustNum = 3;                                      //brust一次開火射出的子彈數(shù)[SerializeField] private float brustTime = 1;                                  //兩次brust開火之間的間隔//[Header("武器狀態(tài)參數(shù)")]private int curAmmo;                                    //當前彈藥量private int curPrepareAmmo;                       //當前后備彈藥量private float shootingIntervalTimer = 0;    //射擊間隔計時器private float brustTimeTimer = 0;               //brust射擊間隔計時器private int brustCounter;                             //brust計數(shù)器[Header("發(fā)射物")][SerializeField] public Transform fireSocket;           [SerializeField] private GameObject bulletPrefab;   public float bulletVelocity = 100;                              public float inertialVelocityMultipler = 10;               public bool constantSpeed = false;                             //本來想做個委托外包出去,想了想不如直接集成在類里得了[Header("特效效果")][SerializeField] private GameObject fireFX;private CinemachineImpulseSource impulseSource;public float cameraShakeMultipler = 1f;[Header("音頻")][SerializeField] private AudioClip fireSound;[SerializeField] private AudioClip reloadSound;[SerializeField] private float soundMultipler = 1f;//玩家的輸入對應的委托轉(zhuǎn)發(fā)public UnityAction onFireStart, onFiring, onFireEnd, onReload;//換彈時的委托,與UI通信使用public UnityAction onReloadStart, onReloadEnd;public UnityAction<float> onReloading;public UnityAction<int, int> onAmmoChanged;//是否選中public UnityAction<bool> onSelectChanged;//自己的狀態(tài)機private StateMachine stateMachine = new StateMachine();public WeaponIdleState idleState;public WeaponFireState fireState;public WeaponReloadState reloadState;private void Awake(){owner = GetComponent<Entity>();impulseSource = fireSocket.GetComponent<CinemachineImpulseSource>();if (weaponSelectIndex == 1)selected = true;//初始化數(shù)據(jù)curAmmo = maxAmmo;curPrepareAmmo = maxPrepareAmmo;brustTimeTimer = brustTime;brustCounter = brustNum;//狀態(tài)初始化idleState = new WeaponIdleState(stateMachine, this);fireState = new WeaponFireState(stateMachine, this);reloadState = new WeaponReloadState(stateMachine, this);//自身賦值到Controller方便其他組件引用PlayerController.Ins.weapons[weaponSelectIndex] = this;}private void Start(){//玩家操作本W(wǎng)eaponowner.onFireStart += () => onFireStart?.Invoke();owner.onFireEnd += () => onFireEnd?.Invoke();owner.onReload += () => onReload?.Invoke();owner.onSelect += (num) =>{selected = num == weaponSelectIndex;onSelectChanged?.Invoke(selected);};owner.onAllSelect += () =>{selected = true;onSelectChanged?.Invoke(selected);};//初始化狀態(tài)機stateMachine.Init(idleState);}private void Update(){stateMachine.Update();if (shootingIntervalTimer > 0)shootingIntervalTimer -= Time.deltaTime;if (brustCounter <= 0 && brustTimeTimer > 0){brustTimeTimer -= Time.deltaTime;if (brustTimeTimer <= 0)brustCounter = brustNum;}if(owner.firing)onFiring?.Invoke();}public void ModifyAmmo(int amount){curAmmo += amount;curAmmo = Mathf.Clamp(curAmmo, 0, maxAmmo);onAmmoChanged?.Invoke(curAmmo, curPrepareAmmo);}public void Fire(){if (!CanFire())return;//發(fā)射投射物Bullet bullet = Instantiate(bulletPrefab, fireSocket.position, fireSocket.rotation).GetComponent<Bullet>();bullet.Init(bulletVelocity, constantSpeed, new Vector3(owner.velocity.x, 0, owner.velocity.z) * inertialVelocityMultipler, owner.flag);//數(shù)據(jù)更新ModifyAmmo(-1);shootingIntervalTimer = shootingInterval;if (fireMode == FireMode.Brust)                 //如果是Brust模式{brustCounter--;if (brustCounter <= 0)brustTimeTimer = brustTime;}//播放槍口特效Instantiate(fireFX, fireSocket.position, fireSocket.rotation);//震動!impulseSource.m_DefaultVelocity.x = Random.Range(-1f, 1f) * cameraShakeMultipler;impulseSource.m_DefaultVelocity.y = Random.Range(-1f, 1f) * cameraShakeMultipler;impulseSource.m_DefaultVelocity.z = Random.Range(-1f, 1f) * cameraShakeMultipler;impulseSource.GenerateImpulse();//槍口音效AudioManager.PlayClipAtPoint(fireSound, fireSocket.position, soundMultipler);}public void Reload(){int needAmmo = maxAmmo - curAmmo;curAmmo = Mathf.Min(curPrepareAmmo, maxAmmo);curPrepareAmmo = Mathf.Max(curPrepareAmmo - needAmmo, 0);onAmmoChanged?.Invoke(curAmmo, curPrepareAmmo);AudioManager.PlayClipAtPoint(reloadSound, owner.transform.position, soundMultipler);}public bool HaveAmmo() => curAmmo > 0;public bool HavePrepareAmmo() => curPrepareAmmo > 0;public bool CanFire(){if (!selected)return false;//沒有子彈if (!HaveAmmo())return false;//沒有結(jié)束冷卻if (shootingIntervalTimer > 0)return false;//如果在Brust模式//如果Counter小于等于0,說明打完了,否則不管//如果打完了并且還沒過brust冷卻,那就不能打if (fireMode == FireMode.Brust && brustCounter <= 0 && brustTimeTimer > 0)return false;return true;}public bool CanBrust() => brustCounter > 0;public float GetReloadTime() => reloadTime;public int GetCurAmmo() => curAmmo;public int GetCurPrepareAmmo() => curPrepareAmmo;public bool CanReload() => curPrepareAmmo > 0 && curAmmo < maxAmmo;public State GetCurState() => stateMachine.curState;
}

武器的主要邏輯存在于狀態(tài)機中

在這里插入圖片描述

但是由于武器的開火分為連發(fā),單發(fā),爆發(fā),因此還需要做一些特殊的處理

以下是WeaponFireState

在使用爆發(fā)模式時,即使玩家松開開火鍵也不能立即停止開火

public class WeaponFireState : WeaponCommonState
{public bool readyEnd;public WeaponFireState(StateMachine stateMachine, Weapon weapon) : base(stateMachine, weapon){}public override void Enter(){base.Enter();weapon.onFireEnd += OnFireEnd;FireOrReload();readyEnd = false;}public override void Exit(){base.Exit();weapon.onFireEnd -= OnFireEnd;}private void OnFireEnd(){if (weapon.fireMode != Weapon.FireMode.Brust)stateMachine.ChangeState(weapon.idleState);readyEnd = true;}public override void Update(){base.Update();//爆發(fā)模式if (weapon.fireMode == Weapon.FireMode.Brust){if (weapon.CanBrust())FireOrReload();else if(readyEnd)stateMachine.ChangeState(weapon.idleState);}else if (weapon.fireMode == Weapon.FireMode.Auto)FireOrReload();}private void FireOrReload(){if (weapon.HaveAmmo()){weapon.Fire();if (!weapon.HaveAmmo())stateMachine.ChangeState(weapon.reloadState);}elsestateMachine.ChangeState(weapon.reloadState);}
}

其他部分較為簡短不特別描述

子彈

子彈同樣使用一個通用的類進行配置

public class Bullet : MonoBehaviour
{[Header("Physical")]private Rigidbody rb;private Vector3 lastPosition;[Header("Attribute")]//子彈所屬派系,可以設定是否開啟友軍傷害,-1為中立派系public int flag = -1;public float velocity = 100;public bool constantSpeed = false;public float lifeTime = 6f;private float lifeTimer;public float gravityMultiper = 1f;[Header("VFX")]public GameObject explosionPrefab;public GameObject trailPrefab;private void Awake(){rb = GetComponent<Rigidbody>();lastPosition = transform.position;lifeTimer = lifeTime;}public void Init(float velocity, bool constantSpeed, Vector3 inertialVelocity /*慣性力*/, int flag = -1){this.velocity = velocity;this.constantSpeed = constantSpeed;rb.velocity += transform.forward * velocity * Time.fixedDeltaTime / rb.mass;rb.AddForce(transform.forward * velocity + inertialVelocity, ForceMode.Impulse);this.flag = flag;}private void Update(){lifeTimer -= Time.deltaTime;if (lifeTimer < 0)OnCollisionEnter(null);}void FixedUpdate(){//防止錯過剛體,對即將經(jīng)過的間隔做一個射線檢測if (Physics.Raycast(lastPosition, rb.velocity.normalized, out RaycastHit hitInfo, rb.velocity.magnitude * Time.fixedDeltaTime)){transform.position = hitInfo.point;rb.velocity = Vector3.zero;return;}//持久動力if (constantSpeed)rb.AddForce(transform.forward * velocity);//調(diào)整旋轉(zhuǎn)朝向transform.forward = rb.velocity.normalized;//應用重力乘數(shù)rb.velocity += new Vector3(0, 9.8f * (1 - gravityMultiper) * Time.fixedDeltaTime, 0);//記錄位置lastPosition = transform.position;}private void OnCollisionEnter(Collision collision){if(collision != null && collision.gameObject.TryGetComponent(out Entity entity)){if (entity.flag == flag)return;}if (trailPrefab){trailPrefab.transform.parent = null;var particleSystems = trailPrefab.GetComponentsInChildren<ParticleSystem>();foreach (var particle in particleSystems){var main = particle.main;main.loop = false;}}Instantiate(explosionPrefab, transform.position, Quaternion.identity);Destroy(gameObject);}private void DelayTrail(){trailPrefab.SetActive(true);}    
}

其內(nèi)部包含初始慣性處理,持續(xù)動力,防止高速穿過物體的處理以及視覺和銷毀時如果有拖尾的處理

第一第三人稱轉(zhuǎn)換

這一塊比較簡單,直接使用Cinemachine自帶的混合,代碼只需要控制兩個虛擬相機的激活即可

public class PlayerCameraController : MonoBehaviour
{//Third Person Camera[SerializeField] private CinemachineVirtualCamera thirdPersonCamera;private Cinemachine3rdPersonFollow thirdCameraBody;public float freeLookSide = 0;public float freeLookDistance = 20;float cameraSide;float cameraDistance;//First Peroson Camera[SerializeField] private CinemachineVirtualCamera firstPersonCamera;private Cinemachine3rdPersonFollow firstCameraBody;private Quaternion lastQuaternion;private void Awake(){thirdCameraBody = thirdPersonCamera.GetCinemachineComponent<Cinemachine3rdPersonFollow>();cameraSide = thirdCameraBody.CameraSide;cameraDistance = thirdCameraBody.CameraDistance;firstCameraBody = firstPersonCamera.GetCinemachineComponent<Cinemachine3rdPersonFollow>();}// Update is called once per framevoid Update(){HandleFreeLook();HandleSwitchView();}private void HandleFreeLook(){if (Input.GetKeyDown(KeyCode.C)){//控制器凍結(jié)lastQuaternion = PlayerController.GetControllerRotation();PlayerController.SetPause(true);//第三人稱參數(shù)thirdCameraBody.CameraSide = freeLookSide;thirdCameraBody.CameraDistance = freeLookDistance;//隱藏準星(有視覺Bug)foreach(var hair in UIManager.Ins.crossHairs){hair.gameObject.SetActive(false);}}if (Input.GetKeyUp(KeyCode.C)){//控制器恢復PlayerController.SetControllerRotation(lastQuaternion);PlayerController.SetPause(false);//第三人稱參數(shù)thirdCameraBody.CameraSide = cameraSide;thirdCameraBody.CameraDistance = cameraDistance;//顯示UIforeach (var hair in UIManager.Ins.crossHairs){hair.gameObject.SetActive(PlayerController.Ins.weapons[hair.weaponIndex].selected);}}}private void HandleSwitchView(){if (Input.GetKeyDown(KeyCode.V)){firstPersonCamera.gameObject.SetActive(!firstPersonCamera.gameObject.activeSelf);thirdPersonCamera.gameObject.SetActive(!thirdPersonCamera.gameObject.activeSelf);}}
}

UI

比較重要的地方是絲滑的UI跟隨以及實時的武器欄

后者只需要在制作時留意委托就可以很方便的調(diào)用,前者則需要一些不同空間的變換知識

準星的跟隨部分

一開始我在Canvas中選擇的渲染模式是覆蓋,后來發(fā)現(xiàn)在覆蓋的模式下不能添加自發(fā)光,導致UI較暗,于是調(diào)整為了攝像機空間,但調(diào)整后導致原本跟蹤正確的準星又不再正確,下面是解決辦法

public class CrossHairUI : MonoBehaviour
{//自身private RectTransform rect, parent;[SerializeField] private GameObject aimHair, reloadHair;[SerializeField] private TextMeshPro reloadTxt;//武器public int weaponIndex = 0;private Weapon weapon;private Transform fireSocket;public float lerpMultipler = 0.1f;void Start(){rect = GetComponent<RectTransform>();parent = rect.parent.GetComponent<RectTransform>();weapon = PlayerController.Ins.weapons[weaponIndex];fireSocket = weapon.fireSocket;weapon.onReloadStart += OnReloadStart;weapon.onReloading += OnReloading;weapon.onReloadEnd += OnReloadEnd;weapon.onSelectChanged += (selected) =>{gameObject.SetActive(selected);};gameObject.SetActive(weapon.selected);}void Update(){if (Physics.SphereCast(fireSocket.position, .5f, fireSocket.forward, out RaycastHit hitInfo, 1000)){if(RectTransformUtility.ScreenPointToLocalPointInRectangle(parent, RectTransformUtility.WorldToScreenPoint(Camera.main, hitInfo.point), Camera.main, out Vector2 localPoint)){rect.localPosition = Vector2.Lerp(rect.localPosition, localPoint, lerpMultipler);}}else{Vector3 point = fireSocket.position + fireSocket.forward * 3000;if (RectTransformUtility.ScreenPointToLocalPointInRectangle(parent, RectTransformUtility.WorldToScreenPoint(Camera.main, point), Camera.main, out Vector2 localPoint)){rect.localPosition = Vector2.Lerp(rect.localPosition, localPoint, lerpMultipler);}}}private void OnReloadStart(){aimHair.SetActive(false);reloadHair.SetActive(true);}private void OnReloading(float remainTime){reloadTxt.SetText(remainTime.ToString("0.00"));}private void OnReloadEnd(){aimHair.SetActive(true);reloadHair.SetActive(false);}
}

在Update中首先SphereCast來獲取擊中的點,再將其WorldToScreenPoint變換到屏幕空間,如果是覆蓋的渲染模式,此時已經(jīng)結(jié)束了,但由于是攝像機模式,因此需要再多一個變換即ScreenPointToLocalPointInRectangle將其變換到面板上的相對位置。之后使用插值即可實現(xiàn)絲滑的跟蹤準

http://m.aloenet.com.cn/news/33966.html

相關文章:

  • 什么是項目管理小小課堂seo自學網(wǎng)
  • 婚紗攝影網(wǎng)站建設新聞稿發(fā)布
  • 珠寶網(wǎng)站設計今日熱點新聞素材
  • sae安裝WordPress4.4合肥品牌seo
  • 蔬菜派送網(wǎng)站怎么做輔導班培訓機構(gòu)
  • 內(nèi)蒙古地區(qū)做推廣網(wǎng)站搜索引擎推廣試題
  • 哈爾濱網(wǎng)站建設技術托管國家再就業(yè)免費培訓網(wǎng)
  • 如何申請域名建立網(wǎng)站資源最全的網(wǎng)盤搜索引擎
  • 網(wǎng)站內(nèi)容營銷武漢seo推廣優(yōu)化公司
  • 做網(wǎng)站個人怎么簽合同長沙全網(wǎng)覆蓋的網(wǎng)絡推廣
  • 網(wǎng)站設計效果專業(yè)樂云seoseo優(yōu)化專員招聘
  • b2b電商網(wǎng)站建設總推薦榜總點擊榜總排行榜
  • 手機商城網(wǎng)站如何開發(fā)一個網(wǎng)站
  • 免費的行情軟件網(wǎng)站不用下載站內(nèi)搜索工具
  • 東莞專業(yè)網(wǎng)站設計咨詢線上運營推廣
  • 網(wǎng)頁游戲排行榜前十名wangyiseo培訓班 有用嗎
  • 天河網(wǎng)站建設制作百度客戶端電腦版下載
  • 怎么做一個論壇網(wǎng)站關鍵詞排名網(wǎng)絡推廣
  • 安卓app開發(fā)框架??趕eo計費
  • 怎么做輪胎網(wǎng)站google官方入口
  • qq刷贊網(wǎng)站怎么做的谷歌瀏覽器網(wǎng)頁版入口
  • 靜態(tài)雙語企業(yè)網(wǎng)站后臺源碼手機網(wǎng)站建設
  • 蘋果app如何做ppt模板下載網(wǎng)站一個產(chǎn)品的宣傳和推廣方案
  • wordpress自適應模版seow
  • 網(wǎng)站開發(fā)的基本條件廣州網(wǎng)站優(yōu)化公司
  • 德陽網(wǎng)站建設重慶seo論壇
  • 畢設網(wǎng)站可以用axure做嗎優(yōu)化服務公司
  • sql網(wǎng)站模板拼多多代運營公司十大排名
  • 在家做兼職的比較靠譜的網(wǎng)站互聯(lián)網(wǎng)銷售
  • 做地推的網(wǎng)站關鍵詞排名怎么做上首頁