1.事件系统 EventSystem
1.1 Drag拖动事件
IInitializePotentialDragHandler:初始化,鼠标最对应地方摁下出发(鼠标Down)每次点击触发一次
IBeginDragHandler:鼠标移动出发,第一下移动触发一次
IDragHandler:一直触发
IEndDragHandler:结束(鼠标Up)鼠标点击松开触发一次
1.2 拖拽与交换物品
例:背包物品交换
给需要交换的物品添加Canvas Group,Box Collider组件以及交换脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
/*
*创建者:
*创建时间:
*描述:
*版本:
*/
public class HomeWork12_9 : MonoBehaviour,IInitializePotentialDragHandler,IBeginDragHandler,IEndDragHandler,IDragHandler
{
CanvasGroup cg;
// Start is called before the first frame update
void Start()
{
cg = GetComponent<CanvasGroup>();//获取Canvas Group组件
}
// Update is called once per frame
void Update()
{
}
public void OnBeginDrag(PointerEventData eventData)
{
cg.blocksRaycasts = false;//当开始拖拽时,该物品设置为不可以被射线碰撞检测(可以穿透,检测下层物品,拖拽时该物品浮于其他物品上方)
}
public void OnDrag(PointerEventData eventData)
{
transform.position=Input.mousePosition;//当停止拖拽时,该物品的位置就是停止时鼠标的位置
}
public void OnEndDrag(PointerEventData eventData)
{
//文本应该单独一个UI层,不检测,文本用于显示背包物品的数量,若交换物品时,鼠标停留的位置刚好处于文本所在的位置,射线检测到的则是文本,物品交换会出现异常(与文本进行交换)
cg.blocksRaycasts = true;//停止拖拽时,该物品不可被穿透,可以被射线碰撞检测
if (eventData.pointerEnter != null && eventData.pointerEnter.gameObject.CompareTag("Equip"))//若碰撞到的物品与拖拽物品具有相同的标签(背包所有物品设置为统一标签,下文有作用)
{
GameObject go = eventData.pointerEnter;
GameObject goParent = go.transform.parent.gameObject;//记录碰撞到的物品的父级(若先进行一方的父级的替换,则两个物品的父级将会是同一个)
go.transform.parent = transform.parent;//将碰撞到的物品的父级重设为拖拽物品的父级,交换父级;
transform.parent=goParent.transform;
go.transform.localPosition = Vector3.zero;//将各自的相对坐标设置为0
transform.localPosition= Vector3.zero;
}
else if (eventData.pointerEnter != null && eventData.pointerEnter.gameObject.CompareTag("Box"))//若碰撞到的是空格子
{
transform.parent = eventData.pointerEnter.transform;//直接将拖拽的物品的父级重置为碰撞的格子
transform.localPosition= Vector3.zero;
}
else
{
transform.localPosition = Vector3.zero;//前文提到的将所有背包物品统一标签作用,若拖拽停止的位置不是背包,则该拖拽物品回到原来位置
}
}
public void OnInitializePotentialDrag(PointerEventData eventData)
{
}
}
点击按钮克隆物品
实现思路1:克隆物体作为子对象,当存在相同物品时,克隆之后进行销毁
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/*
*创建者:
*创建时间:
*描述:
*版本:
*/
public class HomeWork12_9_1 : MonoBehaviour
{
public Text tap;//背包已满提示文本
public GameObject[] gameObjects;//物品预制体
GameObject[] boxs; //背包格子
// Start is called before the first frame update
void Start()
{
boxs = GameObject.FindGameObjectsWithTag("Box");
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
bool b = true;//是否有相同装备
GameObject go= Instantiate(gameObjects[Random.Range(0,gameObjects.Length)]);//随机克隆物品
for (int i = 0; i < boxs.Length; i++)//对背包格子进行遍历
{
if (boxs[i].transform.childCount > 0 && go.name.Equals(boxs[i].transform.GetChild(0).name))//查询背包中是否存在过新克隆出来的物品(若存在则该背包格子子对象数量>0,只需要对子物体数量>0的背包格子进行遍历),若存在物品名称相同则满足条件
{
b=false;//传递出布尔值-有相同物品;
int x=int.Parse( boxs[i].transform.GetChild(0).GetChild(0).GetComponent<Text>().text);
boxs[i].transform.GetChild(0).GetChild(0).GetComponent<Text>().text = (x + 1).ToString();
break;//找到符合条件的背包格子结束遍历,并传递出布尔值;
}
}
bool b1 = true;
if (b)//若无相同装备(b的默认值为true,若上层遍历全部结束并且找到相同物品则布尔值发生改变,值为false)
{
for (int i = 0; i < boxs.Length; i++)//对背包格子进行遍历
{
if (boxs[i].transform.childCount==0)//找到第一个空背包格子(子物体数量==0)
{
b1= false;//传递出布尔值-有空背包格子;
go.transform.SetParent(boxs[i].transform);//将克隆出的物品设置为空背包格子的子物体;
go.transform.localPosition=Vector3.zero;//相对坐标设置为0;
break;
}
}
if (b1)//若无相同装备,并且无空余背包格子(b1默认值为true,若上层遍历全部结束并且找到空背包格子则布尔值发生改变,值为false)
{
tap.transform.gameObject.SetActive(true);//背包已满
}
}
}
}
}
实现思路2,替换图片
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
/*
*创建者:
*创建时间:
*描述:
*版本:
*/
public class Equip : MonoBehaviour,IInitializePotentialDragHandler,IBeginDragHandler,IEndDragHandler,IDragHandler
{
CanvasGroup cg;
public void OnBeginDrag(PointerEventData eventData)
{
cg.blocksRaycasts = false;
}
public void OnDrag(PointerEventData eventData)
{
transform.position = eventData.position;
//transform.position=Input.mousePosition;
}
public void OnEndDrag(PointerEventData eventData)
{
cg.blocksRaycasts = true;
Sprite sprite= null;
sprite = eventData.pointerEnter.GetComponent<Image>().sprite;
eventData.pointerEnter.GetComponent<Image>().sprite=transform.GetComponent<Image>().sprite;
transform.GetComponent<Image>().sprite=sprite;
int temp = 0;
temp=int.Parse(eventData.pointerEnter.transform.parent.GetChild(1).GetComponent<Text>().text);
eventData.pointerEnter.transform.parent.GetChild(1).GetComponent<Text>().text = transform.parent.GetChild(1).GetComponent<Text>().text;
transform.parent.GetChild(1).GetComponent<Text>().text=temp.ToString();
transform.localPosition = Vector3.zero;
eventData.pointerEnter.transform.localPosition= Vector3.zero;
}
public void OnInitializePotentialDrag(PointerEventData eventData)
{
}
// Start is called before the first frame update
void Start()
{
cg= GetComponent<CanvasGroup>();
}
// Update is called once per frame
void Update()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/*
*创建者:
*创建时间:
*描述:
*版本:
*/
public class Bag : MonoBehaviour
{
public GameObject[] prefabs;
GameObject[] bags;
// Start is called before the first frame update
void Start()
{
bags = GameObject.FindGameObjectsWithTag("Box");
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
GameObject go = prefabs[Random.Range(0,prefabs.Length)];
string name = go.GetComponent<Image>().sprite.name;
bool b = true;
for (int i = 0; i < bags.Length; i++)
{
if (bags[i].transform.GetChild(0).GetComponent<Image>().sprite.name.Equals(name))
{
b = false;
int x = int.Parse(bags[i].transform.GetChild(1).GetComponent<Text>().text);
bags[i].transform.GetChild(1).GetComponent<Text>().text = (x + 1).ToString();
break;
}
}
if (b)
{
bool b1=true;
for (int i = 0; i < bags.Length; i++)
{
if (bags[i].transform.GetChild(0).GetComponent<Image>().sprite.name.Equals("Background"))
{
b1 = false;
bags[i].transform.GetChild(0).GetComponent<Image>().sprite=go.GetComponent<Image>().sprite;
break;
}
}
if (b1)
{
print("没有空余");
}
}
}
}
}
1.3鼠标放到图片上面出现提示信息
为游戏对象添加 OnPointerEnter, OnPointerExit两个方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
*创建者:
*创建时间:
*描述:
*版本:
*/
public class _3_8_2 : MonoBehaviour,IPointerEnterHandler, IPointerExitHandler//实现两个对应的接口
{
public void OnPointerEnter(PointerEventData eventData)//鼠标悬浮
{
print("enter");
}
public void OnPointerExit(PointerEventData eventData)//鼠标移出
{
print("exit");
}
}
2.血条跟随
在玩家头顶创建空物体,在空物体中创建Slider作为子对象,并给空物体添加Canvas组件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
*创建者:
*创建时间:
*描述:
*版本:
*/
public class CameraFacing : MonoBehaviour
{
GameObject go;
bool b = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
//没太看懂这两个固定公式
Vector3 targetPos = transform.position + Camera.main.transform.rotation * Vector3.forward;
Vector3 targetUp = Camera.main.transform.rotation * Vector3.up;
transform.LookAt(targetPos,targetUp);
}
}
3.事件委托
注册的方法需要与委托具有相同的返回值类型,相同的参数列表
委托使用三步走:委托声明(通常包含在类中),委托实例化,委托调用
委托声明:访问修饰符 delegate <函数返回类型> <委托名> (<函数参数>)
委托实例化 :委托名 实例名称=new 委托名
委托调用 实例名称(实参)
将方法注册进委托:实例名称=方法名;
实例名称+=方法名;
委托名 实例名称=new 委托名(方法名)