简体   繁体   English

多掷骰子机械师 C# Unity

[英]Multiple dice throw mechanic C# Unity

I would like to istantiate multiple dices (you should be able to add and substract dices) and roll them.我想创建多个骰子(你应该能够添加和减去骰子)并滚动它们。

For now I can roll a dice and get the readout in the console.现在我可以掷骰子并在控制台中获得读数。 My problem: I can't get multiple dice to work...我的问题:我不能让多个骰子工作......

These are the scripts:这些是脚本:

the dice controller:骰子 controller:

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

public class DiceController : MonoBehaviour
{
    public Dice dice;
    public GameObject dicePre;

    public int count = 1;


void Update()
{   
    GameObject[] dices = GameObject.FindGameObjectsWithTag("Dice");
    if(count - 1 == dices.Length){
        for (int i = 0; i < count; i++)
            {
                Instantiate(dicePre, new Vector3(i * 1.1F, 0, 0), Quaternion.identity);
            }
    }
    else if(count -1 < dices.Length){
        return;
    }
}

    public void Throw()
    {
        GameObject[] dices = GameObject.FindGameObjectsWithTag("Dice");
        foreach(GameObject dic in dices){
            dice = dic.GetComponent<Dice>();
            dice.RollDice();
        }
        
    }

    public void Plus(){        //add dice
        count++;
    }

    public void Minus(){       //substract dice
        count--;
    }
}

the dice sides:骰子面:

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

public class DiceSide : MonoBehaviour
{
    bool onGround;
    public int sideValue;

    void OnTriggerStay(Collider col) {
        
        if(col.tag == "ground"){
            onGround = true;
        }
    }

    void OnTriggerExit(Collider col) {
        
        if(col.tag == "ground"){
            onGround = false;
        }
    }

    public bool OnGround(){
        return onGround;
    }

}

the main dice script:主骰子脚本:

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

public class Dice : MonoBehaviour
{
   Rigidbody rb;
   bool hasLanded;
   bool thrown;
   Vector3 initPos;

   public int diceValue;

   public DiceSide[] diceSides;
   
   private void Start(){
        rb = GetComponent<Rigidbody>();
        initPos = transform.position;
        rb.useGravity = false;    
   }


    private void Update(){
        if(Input.GetKeyDown(KeyCode.T)){
            RollDice();
        }

        if(rb.IsSleeping() && !hasLanded && thrown){
            hasLanded = true;
            rb.useGravity = false;
            rb.isKinematic = true;

            SideValueCheck();
        }
        else if(rb.IsSleeping() && hasLanded && diceValue == 0){
            RollAgain();
        }
    }

    public void RollDice(){

        if(!thrown && !hasLanded){
            thrown = true;
            rb.useGravity = true;
            rb.AddTorque(Random.Range(0,500), Random.Range(0,500), Random.Range(0,500));

        }
        else if(thrown && hasLanded){
            Reset();
        }
    }

    void Reset(){

        transform.position = initPos;
        thrown = false;
        hasLanded = false;
        rb.useGravity = false;
        rb.isKinematic = false;
    }

    void RollAgain(){
        Reset();
        thrown = true;
        rb.useGravity = true;
        rb.AddTorque(Random.Range(0,500), Random.Range(0,500), Random.Range(0,500));
    }

    void SideValueCheck(){
        diceValue = 0;
        foreach(DiceSide side in diceSides){
            
            if(side.OnGround()){
                diceValue = side.sideValue;
                Debug.Log("Eine " + diceValue + " wurde gewürfelt!");
            }
        }
    }

}

How can I get this to work?我怎样才能让它工作? also here you can download the unitypackage with everything i got right now: https://workupload.com/file/7brN4gTCeLu也在这里你可以下载我现在得到的所有东西的统一包: https://workupload.com/file/7brN4gTCeLu

First as said I would directly make the prefab field of type首先如前所述,我将直接制作类型的预制字段

public Dice dicePre;

then I would not use FindGameObjectsWithTag all the time to get current instances.那么我不会一直使用FindGameObjectsWithTag来获取当前实例。

I would rather keep track of them in a List like eg我宁愿在List中跟踪它们,例如

public class Dice : MonoBehaviour
{
    // every instance will add itself to this list
    private static List<Dice> instances = new List<Dice>();

    // public read only access
    public static ReadOnlyCollection<Dice> Instances => instances.AsReadOnly();

    // Add yourself to the instances
    private void Awake()
    {
        instances.Add(this);
    }

    // Remove yourself from the instances
    private void OnDestroy()
    {
        instances.Remove(this);
    }
}

So later you can simply use所以以后你可以简单地使用

foreach(var dice in Dice.Instances)
{
    dice.RollDice();
}

The main issue主要问题

Then currently you are checking那么目前你正在检查

if(count - 1 == dices.Length)

and if so you instantiate count dices.如果是这样,你实例化count骰子。

  • So what if your dices is empty and your count is 3 ?那么如果你的骰子是空的并且你的计数是3怎么办? -> nothing would happen -> 什么都不会发生

  • Or what if you already have 2 dices but count is 3 -> you spawn 3 dices and end up with 5 !或者,如果您已经有 2 个骰子但计数为3 -> 您生成3骰子并最终得到5怎么办!

You would need to actually check the difference between the dices amount and count and either add or remove only the difference.您需要实际检查骰子数量和count之间的差异,然后仅添加或删除差异。

In order to fix this I would not do this in Update but rather using a property like为了解决这个问题,我不会在Update中这样做,而是使用类似的属性

[SerializeField] private int _count;

public int Count
{
    get => _count;
    set
    {
        // Count can not be negative
        _count = Mathf.Max(0, value);

        // Now do something with this new value

        // check difference
        var dif = Dice.Instances.Count - _count;

        // if 0 -> nothing to do
        if(dif == 0)
        {
            return;
        }

        // if smaller then 0 -> need more dices
        if(dif < 0)
        {
            for(var i = dif; i < 0; i++)
            {
                Instantiate(dicePre, Vector3.right * Dice.Instances.Count, Quaternion.identity);
            }
        }
        // dif bigger then 0 -> have to many dices
        else
        {
            for(var i = 0; i < dif; i++)
            {
                DestroyImmediate(Dice.Instances[Dice.Instances.Count - 1]);
            }
        }
    }
}

[ContextMenu(nameof(Plus))]
public void Plus()
{      
    Count++;
}

[ContextMenu(nameof(Minus))]
public void Minus()
{  
    Count--;
}

在此处输入图像描述

i do not know unity... so if this is off base with regards to that then i will gladly delete.我不知道团结...所以如果这与此无关,那么我很乐意删除。

public class DiceController : MonoBehaviour
{
    public List<Dice> dices;

    void DiceController()
    {
        dices = new list<Dice>();
        dices.add(new Dice); //ensure always have at least 1 on start
    }

    public void Plus()
    {        
        dices.Add(new Dice);
    }

    //caller can decided, could be random which one get removed.
    //assume they all equal
    public void Minus(Dice dice){  
        dices.Remove(dice);
    }

    public void Throw()
    {
        foreach(Dice dice in dices){
            dice.RollDice();
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM