unity实现一个大乱斗

1. 游戏说明

大乱斗是一种常见的游戏模式,所有角色会进人同一个场景,玩家可以控制它们移动, 也可以让角色攻击敌

  • 打开客户端即视为进入游戏,在随机出生点刷出角色
  • 使用鼠标左键点击场景,角色会自动走到指定位置
  • 在站立状态下,点击鼠标右键可使角色发起攻击,角色会向鼠标指向的方向进行攻击
  • 每个角色默认有100滴血(hp),受到攻击会掉血,死亡后从场景消失,提示"game over"
  • 若玩家掉线,视为死亡,从场景中消失

2. 类结构设计

大乱斗游戏的核心要素之一是玩家所控制的角色,它可以行走,还可以攻击其他角色。 玩 家 可以 操 控 一 个 角 色 ,
又能够看到其他玩家操控的角 色 , 可想而知 , 这 两种 角 色 应 有 不 同 的 表 现 。 玩 家 操 控 的 角 色 是 由 玩家 驱 动 的 ( 下 称 “ 操 控 角 色 ” ), 它 接 受 鼠 标 的控 制 ; 其 他 玩 家 操 控的 角色 (下 称 “ 同步角 色” ) 是 由网 络 数 据 驱 动的 , 由 服 务端 转 发 角 色 的状 态信 息。 这两 种 角色 有 很 多共 同 点,
比 如 都 可以 行 走、 都 可以 表 现攻 击动 作 等。

可以设计图3-8所 示的 类结构,其基类BaseHuman是基础的角色类,它处理“ 操控角 色〞和“同步角色”
的一些共有功能;CtrlHluman类代表“ 操控角色”,它在BaseHluman类的基础上处理鼠标操控功能;SyncHuman
类是“同步角色”类, 它 也 继 承 自 BaseHuman , 并处理网络同步(如果有必要)。

在这里插入图片描述
2.1 BaseHuman类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BaseHuman : MonoBehaviour {
   
    //是否正在移动
	internal bool isMoving = false;
	//移动目标点
	private Vector3 targetPosition;
	//移动速度
	public float speed = 1.2f;
	//动画组件
	private Animator animator;
	//是否正在攻击
	internal bool isAttacking = false;
	internal float attackTime = float.MinValue; //最近攻击时间
	//描述
	public string desc = "";

    // Use this for initialization
	internal void Start () {
   
		animator = GetComponent<Animator>();
	}

	// Update is called once per frame
	internal void Update () {
   
		MoveUpdate();
		AttackUpdate();
	}

    //移动Update
	public void MoveUpdate(){
   
	    //判断当前是否处于行走状态,如果不是行走状态,就不须往目的地行进了
		if(isMoving == false) {
   
			return;
		}
		Vector3 pos = transform.position;
		//MoveTowards的作用是计算pos朝targetPosition方向移动一段距离后的位置
		transform.position = Vector3.MoveTowards(pos, targetPosition, speed*Time.deltaTime);
		//让角色
		transform.LookAt(targetPosition);
		if(Vector3.Distance(pos, targetPosition) < 0.05f){
   
			isMoving = false;
			animator.SetBool("isMoving", false);
		}
	}

    //移动到某处
    public void MoveTo(Vector3 pos) {
   
       targetPosition = pos; //把目的地坐标赋给targetPosition
       isMoving = true; //正在移动
       animator.SetBool("isMoving", true);
    }

    //攻击动作
	public void Attack(){
   
		isAttacking = true;
		attackTime = Time.time;
		animator.SetBool("isAttacking", true);
	}

	//攻击Update
	public void AttackUpdate(){
   
		if(!isAttacking) return;
		if(Time.time - attackTime < 1.2f) return;
		isAttacking = false;
		animator.SetBool("isAttacking", false);
	}
}

在这里插入图片描述

(1) 继承关系
BaseHuman类继承自MonoBehaviour,说明它可以作为组件挂到Gameobject身上,也说明它拥有MonoBehaviour的一些性质,比如在唤醒时会执行Awake和Start,每帧会执行一次Update。
可见继承MonoBehaviour会有Start和Update方法
(2) 移动功能
在这里插入图片描述

  • isMoving是bool型变量,指代角色是否正在移动
  • targetPosition是Vector3类型的坐标,代表角色移动的目的地。
  • MoveTo方法会把目的地的坐标赋给targetPosition,该方法给玩家指定目的地,当玩家点击鼠标时,会调用所控制角色的MoveTo方法,设置目的地坐标targetPosition和动画状态
  • MoveUpdate会让玩家一步步往目的地方向移动,它会每帧执行一次。
  • speed代表移动的速
  • 使用transform.LookAt让角色转向目标点
  • MoveUpdat e 是 一 个 被 Update调用的方 法, 所以它会每帧执行一次。 首先通 过 if (isMoving== false)判断当前是否处于行走状态,如果不是行走状态,就无须往目的地行进了; 接着通过Vector3.MoveTowards 计算新位置 ,MoveTowards的作用 是计算pos 朝 targetPosition 方向移动一段距离后的位置; 之后使用transform.Look At让角色转向目标点; 最后使用Vector3.Distance判断当前位置与目标位置的距离, 如果距离足够小,就认为角色到达了目的地,再将角色状态更改为站立(isMoving=false).

(3)动画功能
BaseHuman中定义了Animator型变量animator,它会指代角色身上的动画控制器。动画控制器中设有isMoving参数,程序通过类似"animator.SetBool(“isMoving”, false);"的语句改变动画控制器的值,从而让角色播放行走和站立两种动画。

2.2 CtrlHuman 操作角色
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CtrlHuman : BaseHuman {
   


	// Use this for initialization
	new void Start () {
   
		base.Start();
	}
	
	// Update is called once per frame
	new void Update () {
   
		base.Update();
		//移动 判断鼠标是否被按下:参数为0表示判断鼠标左键是否被按下
		//Input.mousePosition代表当前鼠标所指的屏幕坐标
		if(Input.GetMouseButtonDown(0)){
   
            // 发出一条射线
			Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
			RaycastHit hit;
			Physics.Raycast(ray, out hit);
			//射线与场景发生碰撞(Tag为Terrain) 那么碰撞点就是角色移动的目标点
			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);
			if(hit.collider.tag != "Terrain") return;
			transform.LookAt(hit.point);
			Attack();
			//发送协议
			string sendStr = "Attack|";
			sendStr += NetManager.GetDesc()+ ",";
			sendStr += transform.eulerAngles.y + ",";
			NetManager.Send(sendStr);
			//攻击判定
			Vector3 lineEnd = transform.position + 0.5f*Vector3.up;
			Vector3 lineStart = lineEnd + 20*transform.forward;
			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);
			}

		}
	}
}

代码说明:
(1) base.xxx, new void xxx()

base 指当前类的父类,可调用父类的非私有属性和方法,代码中的base.Start 和base. Update
指代调用父类BaseHluman的Start 和Update 方法。 new用作修饰符时,new
关键字可以显式地隐藏从基类继承的成员。隐藏继承的成员 时,该成员的派生版本将替换基类版本。虽然可以在不使用new修饰符的情况下隐藏成员,
但会生成警告。

(2)判断鼠标输入

Input.GetMouseButtonDown(0)用 于判断鼠标是否被按 下:参数为0 表示判断鼠标左键 是否被按下,
参数为1表示判断鼠标右键是否被按下。 而 Input.mousePosition代表当前鼠标所指的屏幕坐标。

(3)获取点击位置

Unity3D中的Camera.ScrenPointToRay 方法能够将屏幕位置转成一条射线,只需填入屏幕坐标点 ,
该方法将返回对应的射线。 射线是在三维坐标中一个点向一 个 方 向 发 射 的 一 条线,Unity3D中可以使用Ray
和Physics.Raycast 来做射线检测。当射线射向碰撞器时 Raycast 返回true, 否则为fal se, 并且可以通过out
hi t 变量获取碰撞点。如果射线与场景发 生碰撞(Tag为Terrain),那么碰撞点就是角色移动的目标点。

2.3 syncHuman同步角色

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CtrlHuman : BaseHuman {
   
	// Use this for initialization
	new void Start () {
   
		base.Start();
	}
	
	// Update is called once per frame
	new void Update () {
   
		base.Update();
		//移动
		if(Input.GetMouseButtonDown(0)){
   
			Ray ray = Camera.main
  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值