Unity客户端与Socket服务端通信
代码如下:
1.BaseHuman
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BaseHuman : MonoBehaviour { public Main main;//子类中的main定义无法直接调用,定义在了这里。 public CharacterController mycharCtrler; //是否正在移动 protected bool isMoving = false; //移动目标点 private Vector3 targetPosition; private Vector3 moveDirection = Vector3.zero; //移动速度 public float speed = 4.0f; //动画组件 private Animator animator; //描述 public string desc = ""; //是否正在攻击 internal bool isAttacking = false; internal float attackTime = float.MinValue; //攻击动作 public void Attack() { isAttacking = true; attackTime = Time.time; animator.ResetTrigger("Bow Left Shoot Attack 01"); animator.SetTrigger("Bow Left Shoot Attack 01"); //animator.SetBool("isAttacking",true); } //攻击Update public void AttackUpdate() { if (!isAttacking)return; if(Time.time - attackTime< 1.2f)return; isAttacking = false; animator.ResetTrigger("Bow Left Shoot Attack 01"); //animator.SetBool("isAttacking",false); } //移动到某处 public void MoveTo(Vector3 pos) { targetPosition = pos; isMoving = true; animator.SetBool("Giant Run", true); } //移动Update public void MoveUpdate() { if(isMoving == false) { return; } Vector3 pos = transform.position; moveDirection = targetPosition - transform.position; float dis = Vector3.Distance(pos, targetPosition); Debug.Log(dis); //transform.position = Vector3.MoveTowards(pos,targetPosition,speed* Time.deltaTime); //transform.LookAt(targetPosition); if (dis>0.2f) { //moveDirection = targetPosition - transform.position; moveDirection.y = 0; moveDirection = moveDirection.normalized;//归一化 moveDirection *= speed; mycharCtrler.Move(moveDirection * Time.deltaTime); mycharCtrler.transform.forward = moveDirection; } else { isMoving = false; animator.SetBool("Giant Run", false); } } // Use this for initialization protected void Start() { animator = GetComponent<Animator>(); mycharCtrler = GetComponent<CharacterController>(); } // Update is called once per frame internal void Update() { MoveUpdate(); AttackUpdate(); } }
2.Wander
using System.Collections; using UnityEngine; [RequireComponent(typeof(CharacterController))] [RequireComponent(typeof(SphereCollider))] [RequireComponent(typeof(Animator))] public class Wander : MonoBehaviour { SphereCollider circleCollider; public float pursuitSpeed; public float wanderSpeed; float currentSpeed; public float directionChangeInterval; public bool followPlayer; public float disTance = 5.0f; Coroutine moveCoroutine; //Rigidbody rb2d; CharacterController mycharCtrler; Animator animator; Transform targetTransform = null; Vector3 endPosition; private Vector3 moveDirection = Vector3.zero; float currentAngle = 0; private void Start() { animator = GetComponent<Animator>(); mycharCtrler = GetComponent<CharacterController>(); currentSpeed = wanderSpeed; //rb2d = GetComponent<Rigidbody>(); StartCoroutine(WanderRoutine()); circleCollider = GetComponent<SphereCollider>(); } public IEnumerator WanderRoutine() { while (true) { ChooseNewEndpoint(); if (moveCoroutine != null) { StopCoroutine(moveCoroutine); } moveCoroutine = StartCoroutine(Move(currentSpeed)); yield return new WaitForSeconds(directionChangeInterval); } } void ChooseNewEndpoint() { currentAngle += Random.Range(0, 360); currentAngle = Mathf.Repeat(currentAngle, 360); endPosition += Vector3FromAngle(currentAngle); } Vector3 Vector3FromAngle(float inputAngleDegrees) { float inputAngleRadians = inputAngleDegrees * Mathf.Deg2Rad; return new Vector3(Mathf.Cos(inputAngleRadians), Mathf.Sin(inputAngleRadians), 0); } public IEnumerator Move(float speed) { Vector3 pos = transform.position; float remainingDistance = Vector3.Distance(pos, endPosition); Debug.Log(remainingDistance.ToString()); while (remainingDistance > 1.2f) { if (targetTransform != null) { endPosition = targetTransform.position; } if (remainingDistance > 1.2f) { animator.SetBool("Giant Run", true); //Debug.Log(endPosition); moveDirection = endPosition-transform.position; moveDirection.y = 0; moveDirection *= speed; mycharCtrler.Move(moveDirection * Time.deltaTime); mycharCtrler.transform.forward = moveDirection; remainingDistance = Vector3.Distance(transform.position, endPosition); //Debug.Log(remainingDistance.ToString()); } else { animator.SetBool("Giant Run", false); } yield return new WaitForFixedUpdate(); //yield return new WaitForSeconds(0.0f); } animator.SetBool("Giant Run", false); } private void OnTriggerEnter(Collider collision) { if (collision.gameObject.CompareTag("Player") && followPlayer) { currentSpeed = pursuitSpeed; targetTransform = collision.gameObject.transform; if (moveCoroutine != null) { StopCoroutine(moveCoroutine); } moveCoroutine = StartCoroutine(Move(currentSpeed)); } } private void OnTriggerExit(Collider collision) { if (collision.gameObject.CompareTag("Player")) { animator.SetBool("Giant Run", false); currentSpeed = wanderSpeed; if (moveCoroutine != null) { StopCoroutine(moveCoroutine); } targetTransform = null; } } private void OnDrawGizmos() { if (circleCollider != null) { Gizmos.DrawWireSphere(transform.position, circleCollider.radius); } } private void Update() { Debug.DrawLine(transform.position, endPosition, Color.red); } }
3.SyncHuman
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SyncHuman : BaseHuman { // Start is called before the first frame update new void Start() { base.Start(); } // Update is called once per frame new void Update() { base.Update(); } public void SyncAttack(float eulY) { transform.eulerAngles = new Vector3(0,eulY,0); Attack(); } }
4.PListDropdown
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; public class PListDropdown : MonoBehaviour { public Dropdown dropdown; public InputField inputField; // Start is called before the first frame update void Start() { GetData(); } // Update is called once per frame void Update() { } public void OnDropDownChange() { Debug.Log(dropdown.value.ToString()+dropdown.captionText.text); Debug.Log("xuanxiang1:" + dropdown.options[0].text); if (dropdown.captionText.text == "null") return; PlayerPrefs.SetString("_curName", dropdown.captionText.text); } public void JoinGame() { Debug.Log("JoinGame!"); SceneManager.LoadSceneAsync("main"); } public void CreatNewPlayer() { if (inputField.text == "") return; Debug.Log("CreatNewPlayer!" + inputField.text); if (!SaveData(inputField.text)) return; List<string> newPlayer = new List<string>(); newPlayer.Add(inputField.text); dropdown.AddOptions(newPlayer); } public void GetData() { Debug.Log("Getting Data......"); dropdown.ClearOptions(); string name= PlayerPrefs.GetString("_name0"); if (name =="") { Debug.Log("数据库为空"); return; } string[] names=new string[4]; dropdown.ClearOptions(); for (int i = 0; i < 4; i++) { names[i] = PlayerPrefs.GetString("_name" + i.ToString()); Debug.Log(names[i]); List<string> newPlayer = new List<string>(); newPlayer.Add(names[i]); dropdown.AddOptions(newPlayer); } } public bool SaveData(string name) { Debug.Log("Savingdata,,," + name); if (dropdown.options.Count > 3) { Debug.Log("数据库已经满了!"); return false; } for(int i = 0; i < 4; i++) { if (name == PlayerPrefs.GetString("_name" + i.ToString())) { Debug.Log("重名了!"); return false; } } PlayerPrefs.SetString("_name"+(dropdown.options.Count).ToString(), name); return true; } }
5.CtrlHuman
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class CtrlHuman : BaseHuman { // Start is called before the first frame update new void Start() { base.Start(); } // Update is called once per frame new void Update() { base.Update(); //移动 if (Input.GetMouseButtonDown(0)) { if (EventSystem.current.IsPointerOverGameObject()) return; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; Physics.Raycast(ray, out hit); if (hit.collider.tag == "Terrain") { MoveTo(hit.point); //发送协议 string sendStr = "Move|"; sendStr += NetManager.GetDesc()+","; sendStr += hit.point.x + ","; sendStr += hit.point.y + ","; sendStr += hit.point.z + ","; NetManager.Send(sendStr); } } //攻击 if(Input.GetMouseButtonDown(1)) { if(isAttacking)return; if(isMoving)return; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; Physics.Raycast(ray,out hit); //transform.LookAt(hit.point); Vector3 lookPos = hit.point - transform.position; lookPos.y = 0; mycharCtrler.transform.forward = lookPos; Attack(); //发送协议 string sendStr = "Attack|"; sendStr += NetManager.GetDesc()+","; sendStr += transform.eulerAngles.y + ","; NetManager.Send(sendStr); //攻击判定 Vector3 lineEnd = transform.position + 0.8f * Vector3.up; Vector3 lineStart = lineEnd + 20 * transform.forward; GameObject objMagic = (GameObject)Instantiate(main.magicPrefab); objMagic.transform.position = lineEnd + 3 * transform.forward; //objMagic.transform.Rotate(new Vector3(0, -90, 90)); objMagic.transform.Rotate(transform.rotation.eulerAngles); Rigidbody rigidbody= objMagic.AddComponent<Rigidbody>(); objMagic.AddComponent<CapsuleCollider>(); rigidbody.velocity = transform.forward; Debug.Log("速度:"+rigidbody.velocity); Object.Destroy(objMagic, 2f); if (Physics.Linecast(lineStart,lineEnd,out hit)) { GameObject hitObj = hit.collider.gameObject; if(hitObj == gameObject)return; SyncHuman h = hitObj.GetComponent<SyncHuman>(); if(h == null)return; sendStr = "Hit|"; sendStr += NetManager.GetDesc()+","; sendStr += h.desc + ","; NetManager.Send(sendStr); } } } }
6.Main
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Main : MonoBehaviour { //人物模型预设 public GameObject humanPrefab; public GameObject magicPrefab; public GameObject camObj; //人物列表 [HideInInspector] public BaseHuman myHuman; public Dictionary<string,BaseHuman> otherHumans=new Dictionary<string, BaseHuman>(); // Start is called before the first frame update void Start() { //网络模块 NetManager.AddListener("Enter",OnEnter); NetManager.AddListener("List",OnList); NetManager.AddListener("Move",OnMove); NetManager.AddListener("Leave",OnLeave); NetManager.AddListener("Attack",OnAttack); NetManager.AddListener("Die", OnDie); //NetManager.Connect("127.0.0.1",8888); //添加角色,发送Enter协议 GameObject obj =(GameObject)Instantiate(humanPrefab); float x = Random.Range(-5,5); float z = Random.Range(-5,5); obj.transform.position = new Vector3(x,0,z); CharacterController mycontroller= obj.AddComponent<CharacterController>(); mycontroller.center = new Vector3(0,0.97f, 0); myHuman = obj.AddComponent<CtrlHuman>(); myHuman.desc = NetManager.GetDesc(); myHuman.main = this; Vector3 pos = myHuman.transform.position; Vector3 eul = myHuman.transform.eulerAngles; string sendStr = "Enter|"; sendStr += NetManager.GetDesc()+","; sendStr += pos.x + ","; sendStr += pos.y + ","; sendStr += pos.z + ","; sendStr += eul.y + ","; NetManager.Send(sendStr); //请求玩家列表 NetManager.Send("List|"); } void OnList(string msgArgs) { Debug.Log("OnList" + msgArgs); //解析参数 string[] split = msgArgs.Split(','); int count =(split.Length-1)/6; for(int i = 0; i<count; i++){ string desc = split[i * 6 + 0]; float x = float.Parse(split[i * 6 + 1]); float y = float.Parse(split[i * 6 + 2]); float z = float.Parse(split[i * 6 + 3]); float eulY = float.Parse(split[i * 6 + 4]); int hp = int.Parse(split[i * 6 + 5]); //是自己 if(desc == NetManager.GetDesc()) continue; //添加一个角色 GameObject obj =(GameObject)Instantiate(humanPrefab); obj.transform.position = new Vector3(x,y,z); obj.transform.eulerAngles = new Vector3(0,eulY,0); CharacterController mycontroller = obj.AddComponent<CharacterController>();//添加角色控制器 mycontroller.center = new Vector3(0, 0.97f, 0); BaseHuman h = obj.AddComponent <SyncHuman>(); h.desc = desc; otherHumans.Add(desc,h); } } void OnEnter(string msgArgs) { Debug.Log("OnEnter" + msgArgs); //解析参数 string[] split = msgArgs.Split(','); string desc = split[0]; float x = float.Parse(split[1]); float y = float.Parse(split[2]); float z = float.Parse(split[3]); Debug.Log(split[4]); float eulY = 0.0f; if(float.TryParse(split[4],out eulY)) { Debug.Log(eulY.ToString()); } //是自己 if (desc == NetManager.GetDesc()) return; //添加一个角色 GameObject obj =(GameObject)Instantiate(humanPrefab); obj.transform.position = new Vector3(x,y,z); obj.transform.eulerAngles = new Vector3(0,eulY,0); CharacterController mycontroller = obj.AddComponent<CharacterController>(); mycontroller.center = new Vector3(0, 0.97f, 0); BaseHuman h = obj.AddComponent < SyncHuman >(); h.desc = desc; otherHumans.Add(desc,h); } void OnMove(string msgArgs) { Debug.Log("OnMove" + msgArgs); //解析参数 string[] split = msgArgs.Split(','); string desc = split[0]; float x = float.Parse(split[1]); float y = float.Parse(split[2]); float z = float.Parse(split[3]); //移动 if(!otherHumans.ContainsKey(desc)) return; BaseHuman h = otherHumans[desc]; Vector3 targetPos = new Vector3(x,y,z); h.MoveTo(targetPos); } void OnLeave(string msgArgs) { Debug.Log("OnLeave" + msgArgs); //解析参数 string[] split = msgArgs.Split(','); string desc = split[0]; //删除 if(!otherHumans.ContainsKey(desc)) return; BaseHuman h = otherHumans[desc]; Destroy(h.gameObject); otherHumans.Remove(desc); } void OnAttack(string msgArgs) { Debug.Log("OnAttack" + msgArgs); //解析参数 string[] split = msgArgs.Split(','); string desc = split[0]; float eulY = float.Parse(split[1]); //攻击动作 if(!otherHumans.ContainsKey(desc)) return; SyncHuman h =(SyncHuman)otherHumans[desc]; h.SyncAttack(eulY); } void OnDie(string msgArgs) { Debug.Log("OnDie" + msgArgs); //解析参数 string[] split = msgArgs.Split(','); string hitDesc = split[0]; //自己死了 if(hitDesc == myHuman.desc) { Debug.Log("Game Over"); return; } //死了 if(!otherHumans.ContainsKey(hitDesc))return; SyncHuman h =(SyncHuman)otherHumans[hitDesc]; h.gameObject.SetActive(false); } private void Update() { NetManager.Update(); moveCam(myHuman.gameObject); } void moveCam(GameObject target) { if (target == null) return; camObj.transform.position = target.transform.position; } }
7.NetManager
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Net.Sockets; using UnityEngine.UI; using System; using System.Linq; public static class NetManager { //定义套接字 static Socket socket; //接收缓冲区 static byte[] readBuff = new byte[1024]; //委托类型 public delegate void MsgListener(String str); //监听列表 private static Dictionary<string,MsgListener> listeners = new Dictionary<string,MsgListener>(); //消息列表 static List<String> msgList = new List<string>(); //添加监听 public static void AddListener(string msgName,MsgListener listener) { listeners[msgName] = listener; } //获取描述 public static string GetDesc() { if(socket == null) return ""; if(!socket.Connected) return ""; return socket.LocalEndPoint.ToString(); } //连接 public static void Connect(string ip,int port) { //Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //Connect(用同步方式简化代码) socket.Connect(ip,port); //BeginReceive socket.BeginReceive(readBuff,0,1024,0,ReceiveCallback,socket); Debug.Log("服务器:" + ip.ToString() + ":" + port.ToString() + "已连接!"); } //Receive回调 private static void ReceiveCallback(IAsyncResult ar) { try { Socket socket =(Socket)ar.AsyncState; int count = socket.EndReceive(ar); string recvStr =System.Text.Encoding.Default.GetString(readBuff,0,count); msgList.Add(recvStr); Debug.Log("recv:"+recvStr); socket.BeginReceive(readBuff,0,1024,0,ReceiveCallback,socket); } catch(SocketException ex) { Debug.Log("Socket Receive fail" + ex.ToString()); } } //发送 public static void Send(string sendStr) { if(socket == null)return; if(!socket.Connected)return; //组装协议 byte[] bodyBytes = System.Text.Encoding.Default.GetBytes(sendStr); Int16 len =(Int16)bodyBytes.Length; byte[] lenBytes = BitConverter.GetBytes(len); byte[] sendBytes = lenBytes.Concat(bodyBytes).ToArray(); //为了精简代码:使用同步Send //不考虑抛出异常 socket.Send(sendBytes); Debug.Log("send:"+sendStr); //BeginReceive socket.BeginReceive(readBuff, 0, 1024, 0, ReceiveCallback, socket); } //Update public static void Update() { if(msgList.Count <= 0) return; String msgStr = msgList[0]; msgList.RemoveAt(0); string[] split = msgStr.Split('|'); string msgName = split[0]; string msgArgs = split[1]; Debug.Log(msgName); Debug.Log(msgArgs); //监听回调; if (listeners.ContainsKey(msgName)) { listeners[msgName](msgArgs); } } }
8.Lobby
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; public class Lobby : MonoBehaviour { public Text ipTxt; public Text tipsTxt; public Button connectBtn; public Button startBtn; public void ConnectServer() { try { NetManager.Connect(ipTxt.text, 8888); tipsTxt.gameObject.SetActive(true); startBtn.gameObject.SetActive(true); connectBtn.gameObject.SetActive(false); } catch (Exception ex) { Debug.Log("连接失败!" + ex.ToString()); } } public void startGame() { SceneManager.LoadSceneAsync("playerlist"); } }
9.UI
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UI : MonoBehaviour { public Text nametxt; public GameObject mainMenu; // Start is called before the first frame update void Start() { nametxt.text = PlayerPrefs.GetString("_curName"); } // Update is called once per frame void Update() { } public void ShowObj(GameObject obj) { obj.SetActive(true); } public void HideObj(GameObject obj) { obj.SetActive(false); } }
雁过留声,人死留名。人生仿若风拂沙漠,未留下痕迹……但愿你我之汗水,来得及有所传承……
浙公网安备 33010602011771号