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();
    }
    
}
View Code

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);
    }
}
View Code

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();
  }
}
View Code

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;
    }
}
View Code

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);
            }
        }
    }
}
View Code

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;
    }
}
View Code

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);
    }
  }
}
View Code

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");
    }
}
View Code

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);
    }
}
View Code

 

posted on 2021-03-07 13:11  怪客  阅读(265)  评论(0)    收藏  举报