使用触摸将物体扔到 space 中的特定点

Throwing object to a specific point in space using touch

我正在尝试创建一个小游戏,我可以在其中 select 使用触摸(Touch.position 等)在我的屏幕上(在面板区域内)的一个位置。一旦我有了这个触摸,我就试图将一个物体从静止位置扔到当前触摸位置。我无法将我的 touch.position 转换为我可以从中定位要抛出的对象的转换。到目前为止,我的代码对我不起作用。我很可能会遇到不知道自己不知道的问题。谢谢你的时间。

public int[] distanceToThrow;
public int[] objectToThrow;
public GameObject object;
public Transform throwOrigin;
public float throwingAngle;
public float gravity;
public Transform throwPointPos;
public Transform throwDestination;
public float flightSpeed;

void Update()
{
    if (throwTimer > 0)
    {
        throwTimer -= Time.deltaTime;
        Debug.Log("Timer at: " + throwTimer);
        // Using a single touch as control - Letholor
        if (Input.touchCount > 0)
        {
            Touch touch = Input.GetTouch(0);
            Vector3 touchPos = new Vector3(touch.position.x, touch.position.y, 0);
            Debug.Log("You are touching at position: " + touchPos);
            Ray ray = theCamera.ScreenPointToRay(touchPos);
            RaycastHit hitResult;
            Physics.Raycast(ray, out hitResult);
            Vector3 throwDestination = hitResult.point;
            Debug.Log("Throw destination is " + throwDestination);
            Throw();
        }
    }
}

public void Throw() {

    if (throwTimer > 0)
    {
        Debug.Log("Cooling down.");
        return;
    }

    throwTimer = throwResetTimer;

    Debug.Log("Throwing to " + throwDestination);
    Instantiate(object, throwOrigin.position, throwOrigin.rotation);
        }

Touch.position是屏幕位置。您需要将其转换为世界位置以确定目标坐标。这是我的建议:


第一步:使用Camera.ScreenPointToRay获取世界坐标射线

Vector3 touchPos = new Vector3 (touch.position.x, touch.position.y, 0);
Ray ray = Camera.ScreenPointToRay(touchPos);

你可以想象这就像是 "laser sight" 从相机到触摸的位置。

第二步:使用Physics.Raycast投射射线,得到目标坐标

RaycastHit hitResult;
Physics.Raycast(ray, out hitResult);

请注意,这仅在玩家接触物理碰撞器时有效。如果您希望玩家能够将球扔到 "empty space",您将需要创建一些不可见的墙(显然应该设置为不与球碰撞)以便光线投射可以击中某些东西。最好将隐形墙放置在玩家预期的最大投掷范围内或附近,并将其作为相机的父级,以便获得可预测的行为。

第 3 步:hitResult 现在有了您的目标位置!

Vector3 targetLocation = hitResult.point;

不过,您的代码还有另一个问题。目前,只要玩家将手指放在屏幕上,它就会在每次更新时发射一枚炸弹。那是很多炸弹。有多种方法可以解决这个问题,但我建议使用一个简单的冷却计时器:

float maxCooldown = 1f;
float cooldownTimer = 0f;

void Update()
{
    if (cooldownTimer > 0) cooldownTimer -= Time.deltaTime;  
    [the rest of your update code goes here]
}

public void Throw()
{
    //silently return without throwing, if the cooldown has not expired
    if (cooldownTimer > 0)
        return; 

    //safe to throw - set cooldown to max
    cooldownTimer = maxCooldown;

    [the rest of your throw code goes here]
}

希望对您有所帮助!

编辑:查看您的新代码后,有几处需要修复。

  1. 你想在throwTimer > 0时递减定时器,并在throwTimer <= 0时处理触摸。所以将递减指令保留在原处,并将其余的Update()代码放在一起在 if 语句之外,或者在 else 块中。否则它不会工作。

  2. 我的错误:Camera.ScreenPointToRay 不是静态方法,所以你应该使用 Camera.main.ScreenPointToRay.

  3. throwDestination 应该是 Vector3,但您在程序开始时错误地将其声明为 Transform,并在 Update() 中将其重新声明为 Vector3。要解决此问题,您有两个选择:

    一个。在程序开始时将 ThrowDestination 声明为 Vector3,而不是 Transform,并且不要重新声明它。

    b。将 ThrowDestination 声明为局部变量,不要在脚本的开头声明它,而是将其作为参数直接传递给 Throw()。这就是我在下面的代码中所做的。

  4. 我相信"object"是一个保留字;你不能调用你的射弹 "object"。称它为炸弹、射弹或其他名称。在示例代码中,我将其称为 "projectile".

  5. 您已经在 Throw() 中实例化了对象,但它没有速度并且不知道它的目的地。我们可以稍后解决这个问题;现在,您可能想要确保 Debug.Log 显示您的投掷目的地的合理位置。

void Update()
{
    if (throwTimer > 0)
    {
        throwTimer -= Time.deltaTime;
        Debug.Log("Timer at: " + throwTimer);
    }
    // Using a single touch as control - Letholor
    else if (Input.touchCount > 0)
    {
        Touch touch = Input.GetTouch(0);
        Vector3 touchPos = new Vector3(touch.position.x, touch.position.y, 0);
        Debug.Log("You are touching at position: " + touchPos);
        Ray ray = Camera.main.ScreenPointToRay(touchPos);
        RaycastHit hitResult;
        Physics.Raycast(ray, out hitResult);
        Vector3 throwDestination = hitResult.point;
        Debug.Log("Throw destination is " + throwDestination);
        Throw(throwDestination);
    }
}


public void Throw(Vector3 throwDestination) {
    if (throwTimer > 0)
    {
        Debug.Log("Cooling down.");
        return;
    }
    throwTimer = throwResetTimer;
    Debug.Log("Throwing to " + throwDestination);
    Instantiate(projectile, throwOrigin.position, throwOrigin.rotation);
}

这是更新后的代码。希望对你有帮助。