当前位置:网站首页>Unity学习笔记:联网游戏Pixel Adventure 1学习过程&纠错心得
Unity学习笔记:联网游戏Pixel Adventure 1学习过程&纠错心得
2022-07-03 09:28:00 【百里香酚兰】
Unity学习笔记:联网游戏Pixel Adventure 1学习过程&纠错心得、
之前学校教了一些网络游戏编程的相关内容,跟着学完了感觉还是不会,但是做能联网的游戏又很重要,正好前不久刷到一个合适的教程,B站弹幕评论区一致好评讲的很好,用到的Photon技术学长也推荐,正好最近工程实践项目做得告一段落,于是决定把这个教程找来学学。
https://www.bilibili.com/video/BV1rJ411D7VJ?spm_id_from=333.999.0.0
这个帖子用来记录自己学习途中遇到的一些问题和解决办法,类似于纠错本。
用到的资源链接:
https://assetstore.unity.com/packages/2d/characters/pixel-adventure-1-155360
用到的Photon:
https://dashboard.photonengine.com/en-US
1.资源包加入到我的资源之后点击在Unity中打开没反应
参考链接:
https://blog.csdn.net/qq_15020543/article/details/83382527?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2aggregatepagefirst_rank_ecpm_v1~rank_v31_ecpm-1-83382527-null-null.pc_agg_new_rank&utm_term=%E5%9C%A8unity%E5%95%86%E5%BA%97%E6%89%93%E5%BC%80%E8%B5%84%E6%BA%90%E6%B2%A1%E5%8F%8D%E5%BA%94&spm=1000.2123.3001.4430
但是我就是用的Hub,所以对我来说没什么帮助。
最后我新建了一个空白项目,刚打开就发现可以自动出现自己的资源:
点击右下角,下载之后导入资源包:
(顺便提一句这个好像还是我们工程实践老师提到过的说什么Unity新的Package模式还是什么?我也有点记不太清了)
2.绑定App ID到Pun 2
把自己创建项目的AppID复制下来,粘贴到导入Photon2之后出现的窗口里。

{
PhotonNetwork.ConnectUsingSettings();//链接服务器
}
public override void OnConnectedToMaster()//是否连接到游戏大厅,主服务器
{
base.OnConnectedToMaster();
Debug.Log("连接成功!");
//所有进入同一房间的玩家会在一个屏幕上显示
PhotonNetwork.JoinOrCreateRoom("Room", new Photon.Realtime.RoomOptions() {
MaxPlayers = 4 }, default);
//MaxPlayer最大可20个,default可以换成其他房间属性
}
public override void OnJoinedRoom()
{
base.OnJoinedRoom();
PhotonNetwork.Instantiate("Player", new Vector3(1, 1, 0), Quaternion.identity, 0);
}
// Update is called once per frame
void Update()
{
}
}
挂在Player身上的代码(只有网络相关功能,没有玩家移动转身之类的内容)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
/// <summary>
/// 本脚本用于控制玩家的移动
/// </summary>
public class PlayerMovement : MonoBehaviourPun
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(!photonView.IsMine&&PhotonNetwork.IsConnected)//如果观察的角色是当前客户端并且服务器在运行就继续反之return
{
return;
}
}
}
挂上这两脚本之后,应该能实现运行游戏自动生成玩家和Build Settings窗口和运行模式窗口的玩家同步
5.报错Can not Instantiate before the client joined/created a room. State: ConnectedToMasterServer
经过回看视频检查,发现是创建房间的函数绑定错误,绑成了之前那个应该在第二集开头就被删除的脚本(顺便,可以不删除脚本,把挂有这个脚本的物体删除就行了)
改成新写的JoinOrCreateRoom之后,问题解决
没有报错了。
之前报错是因为这个按钮点击调用了那个被移除的脚本里面的函数,相当于无效点击,自然也没有创建房间,所以报错Can not Instantiate before the client joined/created a room. State: ConnectedToMasterServer
6.角色翻转的时候,角色身上的名字也一起翻转
获取Sprite Renderer组件的Flip参数即可,不使用自己写的代码
因为我没写老师那么完善的代码,他这里面一些变量我也不太知道怎么定义的,就只大致填个框架了。
看弹幕有人说这么写因为没有Photon View Sprite Renderer,所以可能会造成无法同步的情况
我试着找了一下能View Sprite Renderer的脚本,但是并没有找到,又去百度了一下,还没有找到合适的答案
发现一位码友写的链接很有营养:
https://blog.csdn.net/ninesnow_c/article/details/106699608
第二集使用到的C#代码:
为了不报错,我把Flip的部分注释掉了:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using UnityEngine.UI;
/// <summary>
/// 本脚本用于控制玩家的移动
/// </summary>
public class PlayerMovement : MonoBehaviourPun
{
public Text nameText;
public SpriteRenderer sprite;
private void Awake()
{
sprite = GetComponent<SpriteRenderer>();
if(photonView.IsMine)//如果观察到的角色是自己,就把自己的名字给这个对象
{
nameText.text = PhotonNetwork.NickName;
}
else//把正主的名字给这个对象,看到的这个角色是谁就是谁的名字
{
nameText.text = photonView.Owner.NickName;
}
}
public void Flip()//翻转
{
//if(xVelocity<0)
//{
// sprite.flipX = true;
//}
//else if(xVelocity>0)
//{
// sprite.flipX = false;
//}
}
// Update is called once per frame
void Update()
{
if(!photonView.IsMine&&PhotonNetwork.IsConnected)//如果观察的角色是当前客户端并且服务器在运行就继续反之return
{
return;
}
}
}
挂在Level1场景的空物体改名GameManager上的脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
public class GameManager : MonoBehaviourPunCallbacks
{
public GameObject readyButton;
public void ReadyToPlay()
{
readyButton.SetActive(false);
PhotonNetwork.Instantiate("Player", new Vector3(1, 1, 0), Quaternion.identity, 0);
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
挂在Login场景中的NetworkLauncher(空物体改名字)上的脚本NetworkLauncher
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;
public class NetworkLauncher : MonoBehaviourPunCallbacks
{
public GameObject loginUI;
public GameObject nameUI;
public InputField roomName;
public InputField playerName;
// Start is called before the first frame update
void Start()
{
PhotonNetwork.ConnectUsingSettings();
}
public override void OnConnectedToMaster()
{
//base.OnConnectedToMaster();
nameUI.SetActive(true);//如果连接到服务器,登录UI就会显示出来
}
public void PlayButton()
{
nameUI.SetActive(false);
PhotonNetwork.NickName = playerName.text;//名字传输到网络当中
loginUI.SetActive(true);//启用登录UI
}
public void JoinOrCreateButton()
{
//如果没有名字,不能点击按钮
if(roomName.text.Length<2)
{
return;
}
loginUI.SetActive(false);
RoomOptions options = new RoomOptions {
MaxPlayers = 4 };
PhotonNetwork.JoinOrCreateRoom(roomName.text, options, default);//有就加入,没有就创建
}
public override void OnJoinedRoom()
{
base.OnJoinedRoom();
PhotonNetwork.LoadLevel(1);
}
}
7.无法进入同一房间
这个物体是B站网友提出的,我自己倒是没有遇到。
修改Fixed Region,强制进入同一服务器
把下图最下方红框里面网速最快的国家代号填进Fixed Region,这样就能保证客户端都进入这个服务器
8.Ctrl+鼠标点击查看方法详情
9.指定位置生成预制体并设置父物体
这段代码比较有参考价值,我之前也一直不太会写这种,现在遇到了就专门记下来:
10.报错ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
百度了一下这句话,大部分是因为数组越界造成的。
但是我仔细检查了我那点少得可怜的关于数组的代码,好像并没有越界的风险?
而且多反复Build几次之后,出现了新的报错,是Player和RoomListNameButton没有把预制体拖给脚本,所以实例化失败,把这俩问题解决之后所有奇奇怪怪的问题都奇迹般地消失了。
运行效果:
第三集使用到的C#代码:
挂在Login场景里面空物体上RoomListManager的,关于更新房间列表的脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;
public class RoomListManager : MonoBehaviourPunCallbacks
{
public GameObject roomNamePreb;
public Transform gridLayout;//content
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
for(int i=0;i<gridLayout.childCount;i++)
{
//移除所有房间
if(gridLayout.GetChild(i).gameObject.GetComponentInChildren<Text>().text==roomList[i].Name)
{
Destroy(gridLayout.GetChild(i).gameObject);//移除的是UI按钮
//房间里面没人了需要移除房间
if(roomList[i].PlayerCount==0)
{
roomList.Remove(roomList[i]);//移除该房间
}
}
}
foreach(var room in roomList)//遍历房间列表
{
//对象,位置,旋转角度
GameObject newRoom = Instantiate(roomNamePreb, gridLayout.position, Quaternion.identity);
//按钮身上的Text改成房间名字
newRoom.GetComponentInChildren<Text>().text = room.Name +"("+room.PlayerCount+" 人)";//可以自由DIY房间需要显示的信息
//生成的预制体的父物体设置为Content
newRoom.transform.SetParent(gridLayout);
}
}
}
挂在主角行动,负责主角位置同步和主角移动(没有写,可根据需要自行添加主角左右移动之类的代码):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using UnityEngine.UI;
/// <summary>
/// 本脚本用于控制玩家的移动
/// </summary>
public class PlayerMovement : MonoBehaviourPun
{
public Text nameText;
public SpriteRenderer sprite;
private void Awake()
{
sprite = GetComponent<SpriteRenderer>();
if(photonView.IsMine)//如果观察到的角色是自己,就把自己的名字给这个对象
{
nameText.text = PhotonNetwork.NickName;
}
else//把正主的名字给这个对象,看到的这个角色是谁就是谁的名字
{
nameText.text = photonView.Owner.NickName;
}
}
public void Flip()//翻转
{
//if(xVelocity<0)
//{
// sprite.flipX = true;
//}
//else if(xVelocity>0)
//{
// sprite.flipX = false;
//}
}
// Update is called once per frame
void Update()
{
if(!photonView.IsMine&&PhotonNetwork.IsConnected)//如果观察的角色是当前客户端并且服务器在运行就继续反之return
{
return;
}
}
}
挂在Level1场景的空物体GameManager身上的脚本GameManager:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
public class GameManager : MonoBehaviourPunCallbacks
{
public GameObject readyButton;
public void ReadyToPlay()
{
readyButton.SetActive(false);
PhotonNetwork.Instantiate("Player", new Vector3(1, 1, 0), Quaternion.identity, 0);
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
挂在Login场景上的NetworkLauncher上的脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;
public class NetworkLauncher : MonoBehaviourPunCallbacks
{
public GameObject loginUI;
public GameObject nameUI;
public InputField roomName;
public InputField playerName;
public GameObject roomListUI;
// Start is called before the first frame update
void Start()
{
PhotonNetwork.ConnectUsingSettings();
}
public override void OnConnectedToMaster()
{
//base.OnConnectedToMaster();
nameUI.SetActive(true);//如果连接到服务器,登录UI就会显示出来
Debug.Log("Connecter to the Master");
PhotonNetwork.JoinLobby();//加入游戏大厅,这样才可以读取RoomList
}
public void PlayButton()
{
nameUI.SetActive(false);
PhotonNetwork.NickName = playerName.text;//名字传输到网络当中
loginUI.SetActive(true);//启用登录UI
//如果加入大厅,则显示列表UI
if(PhotonNetwork.InLobby)
{
roomListUI.SetActive(true);
}
}
public void JoinOrCreateButton()
{
//如果没有名字,不能点击按钮
if(roomName.text.Length<2)
{
return;
}
loginUI.SetActive(false);
RoomOptions options = new RoomOptions {
MaxPlayers = 4 };
PhotonNetwork.JoinOrCreateRoom(roomName.text, options, default);//有就加入,没有就创建
}
public override void OnJoinedRoom()
{
base.OnJoinedRoom();
PhotonNetwork.LoadLevel(1);
}
}
层级关系如图:
Login场景:
UI层级:
Level1场景:
完整的项目我也会上传CSDN空间,非常简略,除了我提到的这些以外没别的功能。
边栏推荐
- Drop out (pytoch)
- Ut2014 supplementary learning notes
- Free online markdown to write a good resume
- MySQL reports an error "expression 1 of select list is not in group by claim and contains nonaggre" solution
- Content type ‘application/x-www-form-urlencoded;charset=UTF-8‘ not supported
- ThreadLocal principle and usage scenario
- Leetcode刷题---283
- 八、MySQL之事务控制语言
- 丢弃法Dropout(Pytorch)
- Hands on deep learning pytorch version exercise answer - 2.2 preliminary knowledge / data preprocessing
猜你喜欢
Jetson TX2 刷机
The imitation of jd.com e-commerce project is coming
Automatic derivation of introduction to deep learning (pytoch)
C#项目-寝室管理系统(1)
Multilayer perceptron (pytorch)
Training effects of different data sets (yolov5)
Class-Variant Margin Normalized Softmax Loss for Deep Face Recognition
I really want to be a girl. The first step of programming is to wear women's clothes
What did I read in order to understand the to do list
Ut2015 learning notes
随机推荐
Pytorch ADDA code learning notes
Ind yff first week
Leetcode skimming ---75
Mysql5.7 installation and configuration tutorial (Graphic ultra detailed version)
What useful materials have I learned from when installing QT
Stroke prediction: Bayesian
ThreadLocal principle and usage scenario
OpenCV Error: Assertion failed (size.width>0 && size.height>0) in imshow
Timo background management system
Common scenarios in which Seata distributed transactions fail and do not take effect (transactions do not rollback)
Leetcode刷题---278
Ut2012 learning notes
Policy gradient Method of Deep Reinforcement learning (Part One)
Ind kwf first week
Out of the box high color background system
Hands on deep learning pytorch version exercise solution - 2.6 probability
8、 Transaction control language of MySQL
Yolov5 creates and trains its own data set to realize mask wearing detection
Leetcode刷题---10
Leetcode skimming ---44