RPG游戏-好友系统

一、输入框UI脚本:

在后续好友菜单界面需要调用。
1、预制体结构:
RPG游戏-好友系统_第1张图片

2、脚本:

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class UIInputBox : MonoBehaviour
{

    public Text title;
    public Text message;
    public Text tips;
    public Button buttonYes;
    public Button btnCancel;
    public InputField input;

    public Text buttonYesTitle;
    public Text buttonNoTitle;

    public delegate bool SubmitHandler(string inputText, out string tips);
    public event SubmitHandler onSubmit;//通过事件暴露接口、给外部函数执行点击按钮的回调
    public UnityAction OnCancel;
    public string emptyTips;


    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    public void Init(string title, string message, string btnCancel = "", string btnOK = "", string emptyTips = "")
    {
        if (!string.IsNullOrEmpty(title)) this.title.text = title;
        this.message.text = message;
        this.tips.text = null;
        this.onSubmit = null;
        this.emptyTips = emptyTips;
        if (!string.IsNullOrEmpty(btnOK)) this.buttonYesTitle.text = btnOK;
        if (!string.IsNullOrEmpty(btnCancel)) this.buttonNoTitle.text = title;

        this.buttonYes.onClick.AddListener(OnClickYes);
        this.btnCancel.onClick.AddListener(OnClickCancel);
    }

    public void OnClickYes()
    {
        this.tips.text = "";
        if (string.IsNullOrEmpty(input.text))
        {
            this.tips.text = this.emptyTips;
            return;
        }
        if (onSubmit != null)
        {
            string tips;
            if (onSubmit(this.input.text, out tips))
            {
                this.tips.text = tips;
                return;
                    }
        }
        Destroy(this.gameObject);
    }

    public void OnClickCancel()
    {
        Destroy(this.gameObject);
        if (this.OnCancel != null)
            this.OnCancel();
    }
}

实现对以上UI的进行调用和管理:

using UnityEngine;

class InputBox
{
    static Object cacheObject = null;
//参数分别为 需要提示的信息、标题、确定按钮信息、取消按钮信息、输入框为空的提示
    public static UIInputBox Show(string message, string title = "", string btnOK="",string btnCancel="",string emptyTips = "")
    {
        if (cacheObject == null)
        {
            cacheObject = Resloader.Load<Object>("prefab/UIInputBox");
        }

        GameObject go = (GameObject)GameObject.Instantiate(cacheObject);
        UIInputBox inputbox = go.GetComponent<UIInputBox>();
        inputbox.Init(title, message, btnOK, btnCancel, emptyTips);
        return inputbox;
    }
}

二、客户端相关代码

1.好友服务代码
由于加好友是双向的,因此这里的响应和请求也是双向的。

namespace Service
{
    class FriendService : Singleton<FriendService>, IDisposable
    {
        public UnityAction OnFriendUpdate;

        public void Init()
        {

        }
        public FriendService()
        {
            MessageDistributer.Instance.Subscribe<FriendAddRequest>(this.OnFriendAddRequest);
            MessageDistributer.Instance.Subscribe<FriendListResponse>(this.OnFriendList);
            MessageDistributer.Instance.Subscribe<FriendAddResponse>(this.OnFriendAdd);
            MessageDistributer.Instance.Subscribe<FriendRemoveResponse>(this.OnFriendRemove);
        }
        public void Dispose()
        {
            MessageDistributer.Instance.Unsubscribe<FriendAddRequest>(this.OnFriendAddRequest);
            MessageDistributer.Instance.Unsubscribe<FriendListResponse>(this.OnFriendList);
            MessageDistributer.Instance.Unsubscribe<FriendAddResponse>(this.OnFriendAdd);
            MessageDistributer.Instance.Unsubscribe<FriendRemoveResponse>(this.OnFriendRemove);
        }
        //添加好友响应
        private void OnFriendAdd(object sender, FriendAddResponse response)
        {
            if (response.Result == Result.Success)
                MessageBox.Show(response.Request.ToName + "接受了你的请求。", "添加好友成功!");
            else
                MessageBox.Show(response.Errormsg, "添加好友失败!");
        }
         //删除好友响应
        private void OnFriendRemove(object sender, FriendRemoveResponse response)
        {
            if (response.Result == Result.Success)
                MessageBox.Show("删除成功!", "删除好友");
            else
                MessageBox.Show("删除失败!", "删除好友",MessageBoxType.Error);
        }
        //收到好友请求
        private void OnFriendAddRequest(object sender, FriendAddRequest request)
        {
            var confirm = MessageBox.Show(string.Format("{0}请求添加你为好友。", request.FromName), "好友请求",
                MessageBoxType.Confirm,"接受", "拒绝");
            confirm.OnYes = () =>
            {
                this.SendFriendAddResponse(true, request);
            };
            confirm.OnYes = () =>
            {
                this.SendFriendAddResponse(false, request);
            };
        }
        //发送好友请求
        public void SendFriendAddRequest(int friendId, string friendName)
        {
            Debug.Log("SendFriendAdd");
            NetMessage message = new NetMessage();
            message.Request = new NetMessageRequest();
            message.Request.friendAddReq = new FriendAddRequest();
            message.Request.friendAddReq.FromId = User.Instance.CurrentCharacter.Id;
            message.Request.friendAddReq.FromName = User.Instance.CurrentCharacter.Name;
            message.Request.friendAddReq.ToId = friendId;
            message.Request.friendAddReq.ToName = friendName;
            NetClient.Instance.SendMessage(message);
        }
        //回复好友添加响应
        public void SendFriendAddResponse(bool accept, FriendAddRequest request)
        {
            Debug.Log("SendFriendAdd Response");
            NetMessage message = new NetMessage();
            message.Request = new NetMessageRequest();
            message.Request.friendAddRes = new FriendAddResponse();
            message.Request.friendAddRes.Result = accept ? Result.Success : Result.Failed;
            message.Request.friendAddRes.Errormsg = accept ? "添加好友成功!" : "对方拒绝了你的请求!";
            message.Request.friendAddRes.Request = request;
            NetClient.Instance.SendMessage(message);
        }


        public void SendFriendRemoveRequest(int itemid, int friendId)
        {
            Debug.Log("SendFriendRemoveRequest");
            NetMessage message = new NetMessage();
            message.Request = new NetMessageRequest();
            message.Request.friendRemove = new FriendRemoveRequest();
            message.Request.friendRemove.Id = itemid;
            message.Request.friendRemove.friendId = friendId;
            NetClient.Instance.SendMessage(message);
        }
        //更新好友列表
        private void OnFriendList(object sender,FriendListResponse message)
        {
            Debug.Log("OnFriendList");
            FriendManager.Instance.Init(message.Friends);
            if (this.OnFriendUpdate != null) this.OnFriendUpdate();
        }
    }
}

2、好友管理器
用来管理好友列表数据

namespace Managers
{
    
    class FriendManager: Singleton<FriendManager>
    {
        public List<NFriendInfo> allFriends;
        public void Init(List<NFriendInfo> friends)
        {
            this.allFriends = friends;
        }
        
    }
}

3、好友界面UI
这里需要使用到之前编写的输入提示框UI和消息提示UI,由消息服务层来驱动刷新响应
RPG游戏-好友系统_第2张图片

UIFriend (好友列表大界面):


public class UIFriend : MonoBehaviour
{
    public GameObject itemPrefab;
    public ListView listMain;
    public Transform itemRoot;
    public UIFriendItem selectedItem;
    private void Start()
    {
        FriendService.Instance.OnFriendUpdate = RefreshUI;//当好友更新时也会刷新UI
        this.listMain.onItemSelected += this.OnFriendSelected;
        RefreshUI();
    }

    private void RefreshUI()
    {
        ClearFriendList();
        InitFriendItems();
    }

    private void InitFriendItems()
    {
        foreach (var item in FriendManager.Instance.allFriends)
        {
            GameObject go = Instantiate(itemPrefab, this.listMain.transform);
            UIFriendItem ui = go.GetComponent<UIFriendItem>();
            ui.SetFriendInfo(item);
            this.listMain.AddItem(ui);
        }
    }
    private void ClearFriendList()
    {
        this.listMain.RemoveAll();
    }

    public void OnFriendSelected(ListView.ListViewItem item,ListView listView)
    {
        this.selectedItem = item as UIFriendItem;
    }
    public void OnClickFriendAdd()
    {
        //显示提示框
        InputBox.Show("请输入要添加的好友名称或ID", "添加好友").onSubmit += OnFriendAddSubmit;
    }

    public bool OnFriendAddSubmit(string input, out string tips)
    {
        tips = "";
        int friendId = 0;
        string friendName = "";
        if (!int.TryParse(input, out friendId))//先尝试转换成ID
            friendName = input;
        if (friendId == User.Instance.CurrentCharacter.Id || friendName == User.Instance.CurrentCharacter.Name)
        {
            tips = "不能添加自己!";
            return false;
        }
        FriendService.Instance.SendFriendAddRequest(friendId, friendName);//好友请求
        return true;
    }
    public void OnClickFriendChat()
    {
        MessageBox.Show("以后再做");
    }
    public void OnClickdDelete()
    {
        if(selectedItem==null)
        {
            MessageBox.Show("请选择要删除的好友!");
            return;
        }
        var msgbox = MessageBox.Show(string.Format("确定删除好友【[0]】吗?", selectedItem.Info.friendInfo.Name), "删除好友",
             MessageBoxType.Confirm, "删除", "取消");
        msgbox.OnYes = () =>
        {
            FriendService.Instance.SendFriendRemoveRequest(this.selectedItem.Info.Id, this.selectedItem.Info.friendInfo.Id);
        };
    }
}

UIFriendItem :单条好友记录
RPG游戏-好友系统_第3张图片

public class UIFriendItem : ListView.ListViewItem
{
    public Text nickName;
    public Text @class;
    public Text level;
    public Text status;

    public Image background;
    public Sprite normalBg;
    public Sprite selectBg;
    public override void OnSelected(bool selected)
    {
        this.background.overrideSprite = selected ? selectBg : normalBg;
    }
    public NFriendInfo Info;
    void Start()
    {
        
    }
    bool isEquiped = false;
    // Update is called once per frame
    public void SetFriendInfo(NFriendInfo info)
    {
        this.Info = info;
        if (this.nickName != null) this.nickName.text = this.Info.friendInfo.Name;
        if (this.@class != null) this.@class.text = this.Info.friendInfo.Class.ToString();
        if (this.level != null) this.level.text = this.Info.friendInfo.Level.ToString();
        if (this.status != null)
        {
            this.status.text = this.Info.Status == 1 ? "在线" : "离线";
            this.status.color = Color.gray;
            if (this.Info.Status == 1) this.status.color = Color.green;
        }
    }
}

三、服务端相关代码

协议内容

message NFriendInfo
{
	int32 id = 1;
	NCharacterInfo friendInfo = 2;
	int32 status = 3;
}

message FriendAddRequest
{
	int32 from_id = 1;
	string from_name = 2;
	int32 to_id = 3;
	string to_name = 4;
}

message FriendAddResponse
{
	RESULT result = 1;
	string errormsg = 2;
	FriendAddRequest request = 3;
}

message FriendListResponse
{
	RESULT result = 1;
	string errormsg = 2;
	repeated NFriendInfo friends = 3;
}

message FriendRemoveRequest
{
	int32 id = 1;
	int32 friendId = 2;
}

message FriendRemoveResponse
{
	RESULT result = 1;
	string errormsg = 2;
	int32 id = 3;
}

数据库表结构 与character做关联
RPG游戏-好友系统_第4张图片

1、服务层代码

namespace GameServer.Services
{
    class FriendService: Singleton<FriendService>
    {
        public FriendService()
        {
            MessageDistributer<NetConnection<NetSession>>.Instance.Subscribe<FriendAddRequest>(this.OnFriendAddRequest);
            MessageDistributer<NetConnection<NetSession>>.Instance.Subscribe<FriendAddResponse>(this.OnFriendAddResponse);
            MessageDistributer<NetConnection<NetSession>>.Instance.Subscribe<FriendRemoveRequest>(this.OnFriendRemove);
        }

        private void OnFriendRemove(NetConnection<NetSession> sender, FriendRemoveRequest request)
        {
            Character character = sender.Session.Character;
            Log.InfoFormat("OnFriendRemove: character:{0} FriendReletionID:{1}", character.Id, request.Id);
            sender.Session.Response.friendRemove = new FriendRemoveResponse();
            sender.Session.Response.friendRemove.Id = request.Id;
            if (character.FriendManager.RemoveFriendByID(request.Id))//先做自己删除好友
            {//然后在别人的好友列表数据并删除自己
                sender.Session.Response.friendRemove.Result = Result.Success;
                var friend = SessionManager.Instance.GetSession(request.friendId);
                if (friend != null)
                {//在线从管理器移除
                    friend.Session.Character.FriendManager.RemoveFriendByFriendId(character.Id);
                }
                else
                {//不在线从数据找 再移除
                    this.RemoveFriend(request.friendId, character.Id);
                }
                DBService.Instance.Save();
                sender.SendResponse();
            }

        }
        private void RemoveFriend(int charId,int friendId)
        {
            var removeItem = DBService.Instance.Entities.CharacterFriends.FirstOrDefault(v => v.CharacterID == charId && v.FriendID == friendId);
            if(removeItem != null)
            {
                DBService.Instance.Entities.CharacterFriends.Remove(removeItem);
            }
        }
        private void OnFriendAddResponse(NetConnection<NetSession> sender, FriendAddResponse response)
        {
            Character character = sender.Session.Character;
            Log.InfoFormat("OnFriendAddResponse: character:{0} Result:{1} FromId:{2} ToID:{3}",
                character.Id, response.Result, response.Request.FromId, response.Request.ToId);
            sender.Session.Response.friendAddRes = response;
            if (response.Result == Result.Success)
            {//接受了好友添加请求
                var requester = SessionManager.Instance.GetSession(response.Request.FromId);
                if (requester == null)
                {
                    sender.Session.Response.friendAddRes.Result = Result.Failed;
                    sender.Session.Response.friendAddRes.Errormsg = "发起者已离线!";
                }
                else
                {
                    //互相添加好友
                    character.FriendManager.AddFriend(requester.Session.Character); 
                    requester.Session.Character.FriendManager.AddFriend(character);
                    DBService.Instance.Save();
                    requester.Session.Response.friendAddRes = response;
                    requester.Session.Response.friendAddRes.Result = Result.Success;
                    requester.Session.Response.friendAddRes.Errormsg = "添加好友成功!";
                    requester.SendResponse();
                }
            }
            sender.SendResponse();
           
        }

        private void OnFriendAddRequest(NetConnection<NetSession> sender, FriendAddRequest request)
        {
            Character character = sender.Session.Character;
            Log.InfoFormat("OnFriendAddRequest: FromID:{0} FromName:{1} ToID:{2} ToName:{3}",
                request.FromId, request.FromName, request.ToId, request.ToName);
            if (request.ToId == 0)
            {//查找在线所有玩家
                foreach(var cha in CharacterManager.Instance.Characters)
                {
                    if (cha.Value.Data.Name == request.ToName)
                    {
                        request.ToId = cha.Key;
                        break;
                    }
                }
            }
            NetConnection<NetSession> friend = null;
            if (request.ToId > 0)
            {
                if (character.FriendManager.GetFriendInfos(request.ToId) != null)
                {
                    sender.Session.Response.friendAddRes = new FriendAddResponse();
                    sender.Session.Response.friendAddRes.Result = Result.Failed;
                    sender.Session.Response.friendAddRes.Errormsg = "已经是好友了!";
                    sender.SendResponse();
                    return;
                }
                friend = SessionManager.Instance.GetSession(request.ToId);
            }
            if (friend == null)
            {
                sender.Session.Response.friendAddRes = new FriendAddResponse();
                sender.Session.Response.friendAddRes.Result = Result.Failed;
                sender.Session.Response.friendAddRes.Errormsg = "好友不在线或者不存在!";
                sender.SendResponse();
                return;
            }
            Log.InfoFormat("ForwardRequest: FromID:{0}, ToID:{2}", request.FromId, request.ToId);
            friend.Session.Response.friendAddReq = request;//添加好友的响应直接为当前玩家请求 服务器做中转处理
            friend.SendResponse();
        }
    }
}

2、好友管理器
做好友的增删查

namespace GameServer.Managers
{
    class FriendManager
    {
        Character Owner;
        List<NFriendInfo> friends = new List<NFriendInfo>();
        bool friendChanged = false;//好友是否改变 用于同步好友信息
        public FriendManager(Character cha)
        {
            this.Owner = cha;
            this.InitFriends();
        }
        public void GetFriendInfos( List<NFriendInfo> list)
        {
            foreach(var f in this.friends)
            {
                list.Add(f);
            }
        }

        public NFriendInfo GetFriendInfo(int friendId)
        {
            foreach(var f in this.friends)
            {
                if(f.friendInfo.Id == friendId)
                {
                    return f;
                }
            }
            return null;
        }
        private NFriendInfo GetFriendInfo(TCharacterFriend friend)
        {
            NFriendInfo friendInfo = new NFriendInfo();
            //获取在线好友玩家的数据
            var character = CharacterManager.Instance.GetCharacter(friend.FriendID);
            friendInfo.friendInfo = new NCharacterInfo();
            friendInfo.Id = friend.Id;
            if(character == null)
            {//构造离线数据(从数据库更新)
                friendInfo.friendInfo.Id = friend.FriendID;
                friendInfo.friendInfo.Name = friend.FriendName;
                friendInfo.friendInfo.Class = (CharacterClass)friend.Class;
                friendInfo.friendInfo.Level = friend.Level;
                friendInfo.Status = 0;
            }
            else
            {//构造在线数据(从在线玩家管理器更新)
                friendInfo.friendInfo = this.GetBasicInfo(character.Info);
                friendInfo.friendInfo.Name = character.Info.Name;
                friendInfo.friendInfo.Class = character.Info.Class;
                friendInfo.friendInfo.Level = character.Info.Level;
                character.FriendManager.UpdateFriendInfo(this.Owner.Info, 1);
                friendInfo.Status = 1;
            }
            return friendInfo;
        }
        private NCharacterInfo GetBasicInfo(NCharacterInfo info)
        {
            return new NCharacterInfo()
            {
                Id = info.Id,
                Name = info.Name,
                Class = info.Class,
                Level = info.Level
            };
        }

        public void InitFriends()
        {
            this.friends.Clear();
            foreach(var friend in this.Owner.Data.Friends)
            {
                this.friends.Add(GetFriendInfo(friend));
            }
        }
        public void AddFriend(Character friend)
        {
            TCharacterFriend tf = new TCharacterFriend()
            {
                FriendID = friend.Id,
                FriendName = friend.Data.Name,
                Class = friend.Data.Class,
                Level = friend.Data.Level,
            };
            this.Owner.Data.Friends.Add(tf);
            friendChanged = true;
        }
        public bool RemoveFriendByFriendId(int friendid)
        {
            var removeItem = this.Owner.Data.Friends.FirstOrDefault(v => v.FriendID == friendid);
            if (removeItem != null)
            {
                DBService.Instance.Entities.CharacterFriends.Remove(removeItem);
            }
            friendChanged = true;
            return true;
        }
        public bool RemoveFriendByID(int id)
        {
            var removeItem = this.Owner.Data.Friends.FirstOrDefault(v => v.Id == id);
            if (removeItem != null)
            {
                DBService.Instance.Entities.CharacterFriends.Remove(removeItem);
            }
            friendChanged = true;
            return true;
        }

        //处理玩家在线 离线状态
        public void UpdateFriendInfo(NCharacterInfo friendInfo,int status)
        {
            foreach(var f in this.friends)
            {
                if(f.friendInfo.Id == friendInfo.Id)
                {
                    f.Status = status;
                    break;
                }
            }
            this.friendChanged = true;
        }

        //在SESSION发送消息前调用这个 同步好友列表
        public void PostProcess(NetMessageResponse message)
        {
            if (friendChanged)
            {
                this.InitFriends();
                if(message.friendList == null)
                {
                    message.friendList = new FriendListResponse();
                    message.friendList.Friends.AddRange(this.friends);
                }
            }
            friendChanged = false;
        }
    }
}

你可能感兴趣的:(unity,游戏,ui,unity)