繁体   English   中英

Unity3D 中的 Random.Range 没有给出给定范围内的数字

[英]Random.Range in Unity3D is not giving numbers in the range given

所以,我试图找到一个介于 -58.6 和 156.18 之间的随机数。 我想在移动画布对象的位置时将该数字放入 y 值。 这是我的代码:此代码位于画布对象上

using UnityEngine;
public class LaserControl : MonoBehaviour {
    public Transform player;
    public Transform laserStart;
    void Start () {
        //change to 20 and 35

        InvokeRepeating("ShowFork", 5, 10);
    }

    private void ShowFork()
    {

// look at the line below:

        transform.position = new Vector3(transform.position.x,Random.Range(-58.6f ,156.18f),0);
        GetComponent<CanvasGroup>().alpha = 1;
        Invoke("Fire", 3);
    }
    private void Fire() {
        Vector3 screenPoint = Camera.main.ScreenToWorldPoint(new Vector3(transform.position.x-laserStart.position.x,transform.position.y,0));
        float y = screenPoint.y;
        laserStart.transform.position = new Vector3(screenPoint.x, y, laserStart.position.z);
        laserStart.GetComponent<SpriteRenderer>().enabled = true;
        laserStart.GetComponent<ShootBeam>().enabled = true;
        Invoke("Revert", 3);
    }
    private void Revert()
    {
        GetComponent<CanvasGroup>().alpha = 0;
        laserStart.GetComponent<ShootBeam>().enabled = true;
    }
}

无论如何,当发生这种情况时,我得到的值不在范围内。

这是其中之一:-111.9216

我不明白为什么会发生这种情况,因为我以前从未遇到过简单 Random.Range 方法的问题。 不过,这可能是一些非常简单的问题,我是 Unity 的新手。 请帮忙! 谢谢!

首先:

Unity Inspector 中显示的位置始终是相应父对象的本地空间偏移量。

因此,当在全局/绝对世界空间中分配新的transform.position ,如果父对象的转换与默认值不同,则始终会有不同的局部空间偏移

  • 位置: 0,0,0
  • 旋转: 0,0,0
  • 规模: 1,1,1

所以你应该做的是分配和访问localPosition坐标:

transform.localPosition = new Vector3(transform.localPosition.x,Random.Range(-58.6f ,156.18f),0);

除此之外,您GetComponent反复调用GetComponent ,这是非常昂贵的。 您应该初始化您的组件并一次性获取所有必需的引用,存储它们并在以后重用它们:

public Transform player;
public Transform laserStart;

// Of possible already reference these via the Inspector
// Then you could skip the GetComponent entirely
[SerializeField] private CanvasGroup _canvasGroup;
[SerializeField] private SpriteRenderer _laserSpriteRenderer;
[SerializeField] private ShootBeam _laserShootBeam;

// Top secret hint for you ;)
// simply go to the ContextMenu of this component and hit FetchComponents
// Then you don't have to manually reference them.
[ContextMenu (nameof(FetchComponents))]
void FetchComponents() 
{
    if(!_canvasGroup) _canvasGroup = GetComponent<CanvasGroup>();
    if(!_laserSpriteRenderer) _laserSpriteRenderer = laserStart.GetComponent<SpriteRenderer>();
    if(!_laserShootBeam) _laserShootBeam = laserStart.GetComponent<ShootBeam>();
}

private void Start()
{
    FetchComponents();

    //change to 20 and 35
    InvokeRepeating(nameof(ShowFork), 5, 10);
}

private void ShowFork()
{
    transform.localPosition = new Vector3(transform.localPosition.x,Random.Range(-58.6f ,156.18f),0);
    _canvasGroup.alpha = 1;
    Invoke(nameof(Fire), 3);
}

private void Fire()
{
    var screenPoint = Camera.main.ScreenToWorldPoint(new Vector3(transform.position.x-laserStart.position.x, transform.position.y, 0));
    laserStart.transform.position = new Vector3(screenPoint.x, screenPoint.y, laserStart.position.z);
    _laserSpriteRenderer.enabled = true;
    _laserShootBeam.enabled = true;
    Invoke(nameof(Revert), 3);
}

private void Revert()
{
    _canvasGroup.alpha = 0;

    // TODO: I thought you want to revert here?
    _laserShootBeam.enabled = true;
}

一般来说,使用Invoke很好,而且通常是一个不错的选择,但在您的情况下,它可能会变得非常混乱,您必须注意时间安排。 在这里,我宁愿建议使用Coroutine

private void Start()
{
    FetchComponents();
    StartCoroutine(LaserRoutine());
}

private IEnumerator LaserRoutine()
{
    //change to 20 and 35
    // initial wait
    yield return new WaitForSeconds(5.0f);

    // this looks very scary but is fine in a Coroutine
    // as long as you yield somewhere inside!
    while(true)
    {
        // Your former ShowFork
        transform.localPosition = new Vector3(transform.localPosition.x,Random.Range(-58.6f ,156.18f),0);
        _canvasGroup.alpha = 1;

        yield return new WaitForSeconds(3.0f);

        // Your former Fire
        var screenPoint = Camera.main.ScreenToWorldPoint(new Vector3(transform.position.x-laserStart.position.x, transform.position.y, 0));
        laserStart.position = new Vector3(screenPoint.x, screenPoint.y, laserStart.position.z);
        _laserSpriteRenderer.enabled = true;
        _laserShootBeam.enabled = true;

        yield return new WaitForSeconds (3.0f);

        // Your former Revert

        _canvasGroup.alpha = 0;

        // TODO: I thought you want to revert here?
        _laserShootBeam.enabled = false;
        _laserSpriteRenderer.enabled = false;
    }
}

暂无
暂无

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

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