通過前面的制作,我們已經(jīng)能夠讓子彈出現(xiàn),并且射擊,但是如何讓子彈跟隨我們的視角進(jìn)行射擊呢?而不是跟隨槍口實(shí)例化出來的位置進(jìn)行移動(dòng)。
引用攝像機(jī):
void Shoot()
{
playFlash.PlayFalsh();
// 實(shí)例化子彈對(duì)象到當(dāng)前的物體
GameObject go = Instantiate(bullet, transform.position, transform.rotation) as GameObject;
// 獲取當(dāng)前視野
Vector3 current = MainCame.ScreenToWorldPoint(new Vector3(Screen.width / 2, Screen.height / 2, 0));
RaycastHit hit;
bool isCollider = Physics.Raycast(current, MainCame.transform.forward, out hit);
if (isCollider)
{
go.transform.LookAt(hit.point);
}
else
{
current += MainCame.transform.forward * 600;
go.transform.LookAt(current);
}
}
接著導(dǎo)入游戲的運(yùn)行場(chǎng)景,刪除場(chǎng)景中自帶的角色控制器
改個(gè)名字,扔進(jìn)我們的Scenes中
2、制作游戲開始UI
登陸界面:
tween動(dòng)畫下面的finished屬性: 即當(dāng)前動(dòng)畫播放后執(zhí)行什么操作
3、給我們的場(chǎng)景服務(wù)器添加游戲控制器腳本:GameController
4、實(shí)例化我們的角色
我們可以設(shè)置一個(gè)空的游戲?qū)ο螅缓髮⑽覀兊臄橙撕蛻?zhàn)士一同掛在它的子物體下
最好使用NetWork.Instantiate();
5、客戶端鏈接服務(wù)器并創(chuàng)建角色
設(shè)置準(zhǔn)心,
通過GIUTexture來進(jìn)行,看不到可以給它添加一個(gè)子物體的攝像機(jī)。
隱藏鼠標(biāo) 只需要在初始化服務(wù)器,客戶端連接服務(wù)器的方法中:
給創(chuàng)建的角色添加一個(gè)Move 腳本:其中根據(jù)是哪個(gè)端來進(jìn)行控制
之前測(cè)試角色移動(dòng)就是通過下面腳本進(jìn)行,所以我們根據(jù)判斷出那個(gè)客戶端來進(jìn)行控制。
同時(shí)禁用掉射擊功能或者所有的能夠影響兩者的共同腳本:
獲取射擊腳本,設(shè)置射擊腳本的enable 為 false
同時(shí)提供設(shè)置player 的方法:
在我們GameController中:
最終我們要禁止掉的腳本
坑一:
RPC:
RPC 的全稱是 Remote Procedure Call 是一種進(jìn)程間通信方式。它允許程序調(diào)用另一個(gè)地址空間(通常是共享網(wǎng)絡(luò)的另一臺(tái)機(jī)器上)的過程或函數(shù),而不用程序員顯式編碼這個(gè)遠(yuǎn)程調(diào)用的細(xì)節(jié)。即程序員無論是調(diào)用本地的還是遠(yuǎn)程的,本質(zhì)上編寫的調(diào)用代碼基本相同。
遠(yuǎn)程過程調(diào)用(RPC)讓你調(diào)用一個(gè)遠(yuǎn)程計(jì)算機(jī)的函數(shù)。就好像調(diào)用一個(gè)普通函數(shù)一樣容易,但也需要理解.RPC調(diào)用通常用于執(zhí)行一些事件,根據(jù)所有游戲客戶端或者特定的范圍內(nèi)雙方的事件信息。
一些重要的不同
如果發(fā)現(xiàn)角色不能很好的創(chuàng)建,那么我們就需要通過RPC調(diào)用:第一個(gè)參數(shù)方法名字,第二個(gè)所有的客戶端,第三個(gè)前面方法的參數(shù)
方法因?yàn)楸籖PC調(diào)用所以【RPC】標(biāo)注一下:
同理在服務(wù)器連接客戶端的方法中,仿照上述方法,直接就可以搞定兩端的連接了。
如果發(fā)現(xiàn)不能禁止其他客戶端的游戲角色控制,可以重新獲取一次腳本
我們?cè)偻ㄟ^RPC方法調(diào)用方法,需要在方法上面標(biāo)注【PRC】
同步動(dòng)畫效果:
void Update() {
if (player.Hp > 0)
{
if (charactor.isGrounded == false)
{
networkV.RPC("PlayAni", RPCMode.All, s1);
}
else
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
if (Mathf.Abs(h) > 0.2 || Mathf.Abs(v) > 0.2)
{
networkV.RPC("PlayAni", RPCMode.All, s2);
}
else
{
networkV.RPC("PlayAni", RPCMode.All, s3);
}
}
}
else {
if (isPlayDieAni == false)
{
networkV.RPC("PlayAni", RPCMode.AllBuffered, "soldierDieFront");
isPlayDieAni = true;
}
}
}
// 傳入名字播放動(dòng)畫
[RPC]
public void PlayAni(string aniName)
{
// 因?yàn)閟tart方法只調(diào)用一次,剛開始進(jìn)去就會(huì)調(diào)用,而后面就不會(huì)調(diào)用了.
// 如果動(dòng)畫不同步,那么就是我們的Start方法不調(diào)用,所以獲取不到Animation組件
GetComponent<Animation>().CrossFade(aniName, 0.5f);
// 控制動(dòng)畫播放速度
// ani[aniName].speed = 2.0f;
}
來吧少年互相傷害:
6、殺戮時(shí)刻
給子彈腳本添加我們的傷害值
public float damage = 10;
給角色添加生命值
// 接下來在我們子彈方法中:
if(hit.collider.tag == "Player")
{
hit.collider.GetComponent<Player>().TakeDamage(this.damage);
}
//完善死亡動(dòng)畫
在角色控制腳本中完成傷害同步
吸收傷害:
7、音樂:
添加音樂,設(shè)置音樂為2D音樂。
子彈的音樂可以直接扔進(jìn)預(yù)制物中,這樣每次創(chuàng)建出來都會(huì)播放音樂
8、結(jié)束面板
按鈕事件注冊(cè)一下
控制戰(zhàn)斗的勝利或者失敗
隱藏面板顯示我們的結(jié)束面板,同時(shí)顯示鼠標(biāo),繼續(xù)游玩或者退出
9、參考資料
http://blog.csdn.net/w00w12l/article/details/46290865
http://blog.csdn.net/w00w12l/article/details/46290857
http://www.manew.com/youxizz/2390.html
簡(jiǎn)書:Network Lobby
http://blog.csdn.net/u010019717/article/details/46993697
http://blog.csdn.net/u010019717/article/details/46994409
http://blog.csdn.net/u010019717/article/details/47032099