实现效果
效果展示视频 项目Github
功能需求
点击电线组件可以旋转,连接电池首尾游戏结束(该Demo还要连通特殊组件),连通后线路会亮起来(该Demo只要和正极相连的线路就会亮,Demo的亮是图片颜色变化和Unity光照,这里就写图片的颜色变化,思路是差不多的)。不需要记录正确路线的所有电线组件的正确方向,将电路组件做成prefab后,可以由策划自由放置,判断是否连接正确由组件之间的自行判断。
实现思路
为每个电线组件添加接口Trigger,点击组件后组件进行旋转,将接口触发到的线路引用添加进来,将离开的线路引用删除,然后发送事件,重置所有让电池开始从正极的电线开始递归调用显示。
实现过程
创建电线组件
创建一个空物体命名为Line_A并添加Tag为Line,在其下创建俩个空物体,一个命名为Images用来存放图片,一个命名为CheckPoints用来存放检测点并为其子物体添加Tag为CheckPoint。 给Line_添加BoxCollider2D,调整好大小覆盖整个线路,这个Collider是用来检测鼠标的点击旋转的。再给Points下的物体添加BoxCollider2D,并勾选is Trigger,再添加RigidBody2D,并设计BodyType为Kinematic,这个是用来判断线路之间的连接情况的。
给Line_A添加Line.cs脚本,并把图片拖拽上去
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Rendering.Universal;
public class Line : MonoBehaviour
{
public bool isPower;
public List<GameObject> nextLines = new List<GameObject>();
public SpriteRenderer spriteRenderer;
public void Rotate()
{
this.transform.Rotate(0, 0, -90);
}
public void AddNextLine(GameObject line)
{
nextLines.Add(line);
}
public void DeleteNextLine(GameObject line)
{
nextLines.Remove(line);
}
public void Power()
{
Debug.Log(this.transform.name + "通电了");
isPower = true;
SetLuminance(true);
foreach (GameObject nextLine in nextLines)
{
var line = nextLine.GetComponent<Line>();
if (!line.isPower)
{
line.Power();
}
}
}
public void ResetStatic()
{
isPower = false;
SetLuminance(false);
}
public void SetLuminance(bool p)
{
if (p)
{
spriteRenderer.color = new Color32(240, 124, 130, 255);
}
else
{
spriteRenderer.color = new Color(1f, 1f, 1f, 1f);
}
}
}
给CheckPoint添加CheckPoint.cs,并拖拽父对象的引用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CheckPoint : MonoBehaviour
{
public Line line;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("CheckPoint"))
{
line.AddNextLine(other.transform.parent.parent.gameObject);
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("CheckPoint"))
{
line.DeleteNextLine(other.transform.parent.parent.gameObject);
}
}
}
同理,我们可以再设计更多线路预制体
创建电池组件
同理电线的制作 为Battery添加Battery.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Battery : MonoBehaviour
{
public GameObject outLine;
public GameObject inLine;
public void StartPower()
{
if (outLine != null)
{
outLine.GetComponent<Line>().Power();
}
}
}
把Points下的对象的CheckPoint.cs换成InPole.cs和OutPole.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InPole : MonoBehaviour
{
public Battery battery;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("CheckPoint"))
{
battery.inLine = other.transform.parent.parent.gameObject;
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("CheckPoint"))
{
battery.inLine = null;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OutPole : MonoBehaviour
{
public Battery battery;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("CheckPoint"))
{
battery.outLine = other.transform.parent.parent.gameObject;
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("CheckPoint"))
{
battery.outLine = null;
}
}
}
鼠标点击管理类
在场景中创建空物体命名为Cursor Manager,添加CursorManager.cs单例类,鼠标点击后检测周围的碰撞体,如果Tag是Line,则调用它的旋转方法, 然后发送让关卡管理类指挥通电。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CursorManager : Singleton<CursorManager>
{
private Vector3 mouseWorldPos =>
Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0));
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
ClickAction(ObjectAtMousePosition().gameObject);
}
}
private void ClickAction(GameObject clickObject)
{
if (clickObject != null)
{
switch (clickObject.tag)
{
case "Line":
var line = clickObject.GetComponent<Line>();
line?.Rotate();
LevelManager.Instance.StartPowerCommand();
break;
}
}
}
private Collider2D ObjectAtMousePosition()
{
return Physics2D.OverlapPoint(mouseWorldPos);
}
}
单例类
using System;
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
private static T instance;
public static T Instance
{
get { return instance; }
}
protected void Awake()
{
if (instance != null)
Destroy(gameObject);
else
{
instance = (T) this;
}
}
public static bool IsInitialized
{
get { return instance != null; }
}
protected virtual void OnDestroy()
{
if (instance == this)
{
instance = null;
}
}
}
游戏管理类
在场景中创建空物体命名为Level Manager,添加LevelManager.cs单例类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LevelManager : Singleton<LevelManager>
{
public Battery battery;
[Header("场景中存在的线")]
public GameObject[] lines;
private void Start()
{
lines = GameObject.FindGameObjectsWithTag("Line");
}
public void StartPowerCommand()
{
for (int i = 0; i < lines.Length; i++)
{
lines[i].GetComponent<Line>().ResetStatic();
}
Invoke("StartPower", 0.5f);
Invoke("isGameOver", 0.5f);
}
private void StartPower()
{
battery.StartPower();
}
private void isGameOver()
{
GameObject gameObject = battery.inLine;
if (gameObject != null)
{
if (gameObject.GetComponent<Line>().isPower)
GameOver();
}
}
private void GameOver()
{
Debug.Log("GameOver");
}
}
关卡设计
把所有东西添加成预制体,就可以自由地开始关卡设计了 按住Ctrl可以控制移动距离,还可以自己设置距离
总结
多喝热水、少熬夜,心情美美的,一切问题都会应难而解。
|