场景是,我的场景中有15个对象,每个游戏对象都有自己的网格,所以当玩家用鼠标点击游戏对象时,我想改变游戏对象的颜色,如果玩家多次点击相同的游戏对象,游戏对象应该随机改变颜色,如果玩家在20秒内没有点击场景,则应激活一个按钮,要求玩家加载新场景,并且我的所有游戏对象都应在新场景中生成,在新场景下,玩家必须在15秒内点击所有15个对象,如果他在15秒内点击所有对象,则游戏将结束,否则游戏将重新加载第一个场景,
只是为了澄清你想要实现的目标,据我所知:
- 您在"场景A">
- 每当一个对象被点击时,它随机地改变它的颜色(比方说它变成"激活的"(
- 之后???秒激活的对象再次变为非激活状态并返回到原始颜色
- 如果用户设法使它们在15秒内同时着色(活动(;场景B";已加载
所以我宁愿有一个关于你的可点击对象的非常简单的类,比如
using System.Collections.Generic;
using UnityEngine;
public class ClickableObject : MonoBehaviour
{
// Will hold the references to all currently existing ClickableObject instances
private static readonly List<ClickableObject> _instances = new List<ClickableObject>();
[Header("References")]
[SerializeField] private Renderer _renderer;
[Header("debugging")]
[SerializeField] private bool isActivated;
[SerializeField] private Color _originalColor;
// public read-only accesses
public bool IsActivated => isActivated;
public static IReadOnlyList<ClickableObject> Instances => _instances;
private void Awake()
{
_instances.Add(this);
if (!_renderer)
{
_renderer = GetComponent<Renderer>();
}
_originalColor = _renderer.material.color;
}
private void OnDestroy()
{
_instances.Remove(this);
}
public void SetActivated(bool activated)
{
isActivated = activated;
_renderer.material.color = activated ? new Color(Random.value, Random.value, Random.value, 1.0f) : _originalColor;
}
}
然后在一个中央控制器中处理点击和超时,例如
using System;
using System.Collections;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ClickController : MonoBehaviour
{
[Header("References")]
// If possible already reference this via the Inspector
[SerializeField] private Camera _mainCamera;
[Header("Settings")]
// Configure this via the Inspector
[SerializeField] private float timeout = 15f;
// Configure this via the Inspector and select the layer you have assigned to the clickable objects
[SerializeField] private LayerMask clickableObjectsLayer = LayerMask.NameToLayer("Default");
// configure this via the Inspector and enter the name or path of your target scene to load
[SerializeField] private string targetScene = "sceneB";
// will store a reference to the currently running reset routine
private Coroutine currenResetRoutine;
private void Awake()
{
if (_mainCamera) _mainCamera = Camera.main;
}
private void Start()
{
// Initially reset all objects to be not "activated"
ResetClickableObjects();
}
private void Update()
{
// wait for a mouse click
if (Input.GetMouseButtonDown(0))
{
// shoot out a raycast and check if you hit something on the clickableObjectsLayer
var ray = _mainCamera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit, float.PositiveInfinity, clickableObjectsLayer))
{
// Just to be sure check if it is really a ClickableObject
if (hit.transform.TryGetComponent<ClickableObject>(out var clickableObject))
{
// Check if this is not active yet, otherwise ignore the click
if (!clickableObject.IsActivated)
{
// set this object to active -> colored
clickableObject.SetActivated(true);
// if there is no reset routine running start one with the first clicked object
// => from now on have "timout" seconds to click also the rest of the objects
if (currenResetRoutine != null)
{
currenResetRoutine = StartCoroutine(ResetAfterFifteenSecondsRoutine());
}
// Check if all objects are active at the same time
if (ClickableObject.Instances.All(co => co.IsActivated))
{
// cancel the reset routine
StopCoroutine(currenResetRoutine);
// load the targetScene after 2 seconds
// just to have time for e.g. a "YEAH YOU DID IT YOU AWESOME USER!"
// we use "Invoke" since it also works on a disabled component
Invoke(nameof(LoadScene), 2f);
// disable this component so no clicks are tracked anymore
enabled = false;
}
}
}
}
}
}
private void LoadScene()
{
// Go to the target scene configured in the Inspector
SceneManager.LoadScene(targetScene);
}
private static void ResetClickableObjects()
{
// Reset all ClickableObject to be not activated
foreach (var clickableObject in ClickableObject.Instances)
{
clickableObject.SetActivated(false);
}
}
private IEnumerator ResetAfterFifteenSecondsRoutine()
{
// wait for the timeout configured in the Inspector
yield return new WaitForSeconds(timeout);
// Then reset all ClickableObject to be not activated
ResetClickableObjects();
// reset to allow the next timeout to begin
currenResetRoutine = null;
}
}