使用触摸将物体扔到 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]
}
希望对您有所帮助!
编辑:查看您的新代码后,有几处需要修复。
你想在throwTimer > 0时递减定时器,并在throwTimer <= 0时处理触摸。所以将递减指令保留在原处,并将其余的Update()代码放在一起在 if 语句之外,或者在 else 块中。否则它不会工作。
我的错误:Camera.ScreenPointToRay 不是静态方法,所以你应该使用 Camera.main.ScreenPointToRay.
throwDestination 应该是 Vector3,但您在程序开始时错误地将其声明为 Transform,并在 Update() 中将其重新声明为 Vector3。要解决此问题,您有两个选择:
一个。在程序开始时将 ThrowDestination 声明为 Vector3,而不是 Transform,并且不要重新声明它。
b。将 ThrowDestination 声明为局部变量,不要在脚本的开头声明它,而是将其作为参数直接传递给 Throw()。这就是我在下面的代码中所做的。
我相信"object"是一个保留字;你不能调用你的射弹 "object"。称它为炸弹、射弹或其他名称。在示例代码中,我将其称为 "projectile".
您已经在 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);
}
这是更新后的代码。希望对你有帮助。
我正在尝试创建一个小游戏,我可以在其中 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]
}
希望对您有所帮助!
编辑:查看您的新代码后,有几处需要修复。
你想在throwTimer > 0时递减定时器,并在throwTimer <= 0时处理触摸。所以将递减指令保留在原处,并将其余的Update()代码放在一起在 if 语句之外,或者在 else 块中。否则它不会工作。
我的错误:Camera.ScreenPointToRay 不是静态方法,所以你应该使用 Camera.main.ScreenPointToRay.
throwDestination 应该是 Vector3,但您在程序开始时错误地将其声明为 Transform,并在 Update() 中将其重新声明为 Vector3。要解决此问题,您有两个选择:
一个。在程序开始时将 ThrowDestination 声明为 Vector3,而不是 Transform,并且不要重新声明它。
b。将 ThrowDestination 声明为局部变量,不要在脚本的开头声明它,而是将其作为参数直接传递给 Throw()。这就是我在下面的代码中所做的。
我相信"object"是一个保留字;你不能调用你的射弹 "object"。称它为炸弹、射弹或其他名称。在示例代码中,我将其称为 "projectile".
您已经在 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);
}
这是更新后的代码。希望对你有帮助。