如何在Unity中自动结束游戏?
How to end game automatically in Unity?
我遵循了 YouTube 上的教程(可在 link 获得)来展示如何 drag/drop 我的游戏中的物品。有谁知道我如何调整代码让游戏自动结束或在所有图块都放置在可用插槽中时更改场景?我还想知道是否有任何方法可以限制用户将瓷砖放到已经有瓷砖的插槽上?
这是我已经拥有的所有源代码:
老虎机源代码
public class Slot : MonoBehaviour, IDropHandler {
public GameObject item {
get {
if(transform.childCount>0){
return transform.GetChild (0).gameObject;
}
return null;
}
}
#region IDropHandler implementation
public void OnDrop (PointerEventData eventData)
{
if(!item){
DragHandeler.itemBeingDragged.transform.SetParent (transform);
ExecuteEvents.ExecuteHierarchy<IHasChanged>(gameObject,null,(x,y) => x.HasChanged ());
}
}
DragHandler 源代码:
public void OnBeginDrag (PointerEventData eventData)
{
itemBeingDragged = gameObject;
startPosition = transform.position;
startParent = transform.parent;
GetComponent<CanvasGroup>().blocksRaycasts = false;
}
#endregion
#region IDragHandler implementation
public void OnDrag (PointerEventData eventData)
{
transform.position = eventData.position;
}
#endregion
#region IEndDragHandler implementation
public void OnEndDrag (PointerEventData eventData)
{
itemBeingDragged = null;
GetComponent<CanvasGroup>().blocksRaycasts = true;
if(transform.parent == startParent){
transform.position = startPosition;
}
}
要改变场景你需要使用这个:
SceneManager.LoadScene(scenename);
如果您还需要帮助您了解将其放在项目中的逻辑位置 - 请添加您的代码和更多关于您正在做的事情的解释,而不是 link 一些教程的 22 分钟.
更新:
当所有插槽都已满时,您可以通过以下方式更改场景:
public void OnDrop (PointerEventData eventData)
{
if(!item)
{
DragHandeler.itemBeingDragged.transform.SetParent (transform);
ExecuteEvents.ExecuteHierarchy<IHasChanged>(gameObject,null,(x,y) => x.HasChanged ());
// This code will check if all slots are full and load new scene if they are
// If you already have an array/list of all your slots, you can replace this "FindObjectsOfType" with it
Slot[] allSlots = FindObjectsOfType<Slot>();
bool areAllBackpackSlotsFull = true;
foreach (Slot slot in allSlots)
{
if (slot.isBackpack == true && slot.item == null)
{
areAllBackpackSlotsFull = false;
break;
}
}
if (areAllBackpackSlotsFull)
{
string nextSceneName = "YourScene"; // Place the name of scene you want to load next
UnityEngine.SceneManagement.SceneManager.LoadScene(nextSceneName);
}
}
}
您还问过:
I'd also like to know if there's any way to restrict the user from
dropping a tile onto a slot which has one on it already?
但我看到它似乎已经在您的代码中实现了。在 Slot 的 "OnDrop" 函数中检查当前项目是否为 null,这应该完全按照您的要求进行 - 仅当 slot 为空时才放置图块。所以它已经应该受到限制了。你确定不是吗?
更新二:
更新关于背包和物品栏的新问题。您可以在 Slot class 中添加一些 bool 变量来区分背包和库存:
public class Slot : MonoBehaviour, IDropHandler
{
public bool isBackpack = false;
...
然后在编辑器中将所有背包槽中的 "isBackpack" 变量标记为 true。这将是区分它们的简单方便的方法。
我还更新了上面的代码(检查背包是否已满),所以它现在只会检查背包槽。
更新 3:
我注意到您在评论中提出了另一个问题:
Would there be a way to lock a tile once it has been dragged from the inventory and dropped to the 'backpack'? i.e. that they can't move it again?
这显然与原来的 post 和问题无关,但是好吧,我也会尽力帮助解决这个问题...
我认为像这样的东西可以实现你想要的(我已经改变了你的 DragHandler 代码):
public void OnBeginDrag (PointerEventData eventData)
{
Slot currentSlot = gameObject.GetComponentInParent<Slot>();
if (currentSlot.isBackpack == false)
{
itemBeingDragged = gameObject;
startPosition = transform.position;
startParent = transform.parent;
GetComponent<CanvasGroup>().blocksRaycasts = false;
}
else
{
itemBeingDragged = null;
}
}
#endregion
#region IDragHandler implementation
public void OnDrag (PointerEventData eventData)
{
if (itemBeingDragged != null)
transform.position = eventData.position;
}
#endregion
#region IEndDragHandler implementation
public void OnEndDrag (PointerEventData eventData)
{
if (itemBeingDragged != null)
{
itemBeingDragged = null;
GetComponent<CanvasGroup>().blocksRaycasts = true;
if(transform.parent == startParent)
transform.position = startPosition;
}
}
希望对您有所帮助。
P.S. 我已经帮你解决了 5 个不同的问题。拜托,如果您还有其他问题,与原始 post 无关 - 我建议接受答案以关闭此问题,并在单独的 post 中提出其他问题,并提供新的更新代码和信息(您可以在新的 posts(questions) 中将 link 添加到此 post。因为这不是使用这个网站的正确方式,在评论中提出新的不相关的问题并不断更新问题和答案,这很不方便。
我遵循了 YouTube 上的教程(可在 link 获得)来展示如何 drag/drop 我的游戏中的物品。有谁知道我如何调整代码让游戏自动结束或在所有图块都放置在可用插槽中时更改场景?我还想知道是否有任何方法可以限制用户将瓷砖放到已经有瓷砖的插槽上? 这是我已经拥有的所有源代码:
老虎机源代码
public class Slot : MonoBehaviour, IDropHandler {
public GameObject item {
get {
if(transform.childCount>0){
return transform.GetChild (0).gameObject;
}
return null;
}
}
#region IDropHandler implementation
public void OnDrop (PointerEventData eventData)
{
if(!item){
DragHandeler.itemBeingDragged.transform.SetParent (transform);
ExecuteEvents.ExecuteHierarchy<IHasChanged>(gameObject,null,(x,y) => x.HasChanged ());
}
}
DragHandler 源代码:
public void OnBeginDrag (PointerEventData eventData)
{
itemBeingDragged = gameObject;
startPosition = transform.position;
startParent = transform.parent;
GetComponent<CanvasGroup>().blocksRaycasts = false;
}
#endregion
#region IDragHandler implementation
public void OnDrag (PointerEventData eventData)
{
transform.position = eventData.position;
}
#endregion
#region IEndDragHandler implementation
public void OnEndDrag (PointerEventData eventData)
{
itemBeingDragged = null;
GetComponent<CanvasGroup>().blocksRaycasts = true;
if(transform.parent == startParent){
transform.position = startPosition;
}
}
要改变场景你需要使用这个:
SceneManager.LoadScene(scenename);
如果您还需要帮助您了解将其放在项目中的逻辑位置 - 请添加您的代码和更多关于您正在做的事情的解释,而不是 link 一些教程的 22 分钟.
更新:
当所有插槽都已满时,您可以通过以下方式更改场景:
public void OnDrop (PointerEventData eventData)
{
if(!item)
{
DragHandeler.itemBeingDragged.transform.SetParent (transform);
ExecuteEvents.ExecuteHierarchy<IHasChanged>(gameObject,null,(x,y) => x.HasChanged ());
// This code will check if all slots are full and load new scene if they are
// If you already have an array/list of all your slots, you can replace this "FindObjectsOfType" with it
Slot[] allSlots = FindObjectsOfType<Slot>();
bool areAllBackpackSlotsFull = true;
foreach (Slot slot in allSlots)
{
if (slot.isBackpack == true && slot.item == null)
{
areAllBackpackSlotsFull = false;
break;
}
}
if (areAllBackpackSlotsFull)
{
string nextSceneName = "YourScene"; // Place the name of scene you want to load next
UnityEngine.SceneManagement.SceneManager.LoadScene(nextSceneName);
}
}
}
您还问过:
I'd also like to know if there's any way to restrict the user from dropping a tile onto a slot which has one on it already?
但我看到它似乎已经在您的代码中实现了。在 Slot 的 "OnDrop" 函数中检查当前项目是否为 null,这应该完全按照您的要求进行 - 仅当 slot 为空时才放置图块。所以它已经应该受到限制了。你确定不是吗?
更新二:
更新关于背包和物品栏的新问题。您可以在 Slot class 中添加一些 bool 变量来区分背包和库存:
public class Slot : MonoBehaviour, IDropHandler
{
public bool isBackpack = false;
...
然后在编辑器中将所有背包槽中的 "isBackpack" 变量标记为 true。这将是区分它们的简单方便的方法。
我还更新了上面的代码(检查背包是否已满),所以它现在只会检查背包槽。
更新 3:
我注意到您在评论中提出了另一个问题:
Would there be a way to lock a tile once it has been dragged from the inventory and dropped to the 'backpack'? i.e. that they can't move it again?
这显然与原来的 post 和问题无关,但是好吧,我也会尽力帮助解决这个问题...
我认为像这样的东西可以实现你想要的(我已经改变了你的 DragHandler 代码):
public void OnBeginDrag (PointerEventData eventData)
{
Slot currentSlot = gameObject.GetComponentInParent<Slot>();
if (currentSlot.isBackpack == false)
{
itemBeingDragged = gameObject;
startPosition = transform.position;
startParent = transform.parent;
GetComponent<CanvasGroup>().blocksRaycasts = false;
}
else
{
itemBeingDragged = null;
}
}
#endregion
#region IDragHandler implementation
public void OnDrag (PointerEventData eventData)
{
if (itemBeingDragged != null)
transform.position = eventData.position;
}
#endregion
#region IEndDragHandler implementation
public void OnEndDrag (PointerEventData eventData)
{
if (itemBeingDragged != null)
{
itemBeingDragged = null;
GetComponent<CanvasGroup>().blocksRaycasts = true;
if(transform.parent == startParent)
transform.position = startPosition;
}
}
希望对您有所帮助。
P.S. 我已经帮你解决了 5 个不同的问题。拜托,如果您还有其他问题,与原始 post 无关 - 我建议接受答案以关闭此问题,并在单独的 post 中提出其他问题,并提供新的更新代码和信息(您可以在新的 posts(questions) 中将 link 添加到此 post。因为这不是使用这个网站的正确方式,在评论中提出新的不相关的问题并不断更新问题和答案,这很不方便。