【问题标题】:Rotate then move object in Random direction in Unity在 Unity 中以随机方向旋转然后移动对象
【发布时间】:2019-08-29 01:08:50
【问题描述】:

我正在尝试在 Unity 中创建一个脚本,当另一个对象触摸它时,它会抓住该对象,沿随机方向旋转它并启动它,但我只想在 z 轴上旋转并启动另一个对象.

这是我的脚本:

public BallController ballController;
private GameObject ball;
private Rigidbody2D ballRb;

 void OnTriggerEnter2D(Collider2D other)
{
    ball = other.gameObject;
    ballRb = ball.GetComponent<Rigidbody2D>();
    ball.transform.position = this.transform.position;
    // Freeze the ball
    ballRb.velocity = Vector2.zero;
    // Rotate the ball
    ball.transform.rotation = Quaternion.Euler(0, 0, Random.Range(0, 360));
    // Start moving the ball again
    ballRb.velocity = ballRb.velocity * ballController.bulletSpeed * Time.deltatime;

}

另一个脚本(球)有一个 Ridgidbody 并由另一个对象发射到这个脚本中,脚本让球按我想要的方式旋转,但它不会让球再次移动。

ballController 在编辑器中设置,bulletSpeed 只是我希望球移动的 int(当前设置为 6)。

【问题讨论】:

  • 速度为零,这就是它不移动的原因。检查 bulletSpeed 和 deltatime 但我相信这是由于将速度设置为 Vector2.zero。要使对象在 z 方向上移动,向量的 x 和 y 分量必须为零,z 分量必须不为零。
  • 我刚刚尝试禁用它,现在球移动了,但随机旋转停止工作,现在它抓住了球,不旋转它,然后再次将其发送出去。
  • @jdweng 我怀疑你想在 2D 游戏中向z 方向扔东西;)

标签: c# unity3d rotation 2d


【解决方案1】:

在处理Rigidbody2D 时,您不应使用transform 设置旋转,而应使用ballRb.rotation

稍后你会使用

ballRb.velocity = ballRb.velocity * ballController.bulletSpeed * Time.deltatime;

但在你设置之前

ballRb = Vector2.zero;

所以乘法结果为Vector2.zero。在这个一次性作业中添加 Time.deltaTime(typo btw) 也没有任何意义。

此外,如果您删除这条线,则在分配新速度时不会考虑新的旋转。

velocity 在全局空间中。你也不能使用例如transform.right 作为新方向,因为变换没有更新.. Rigidbody2D 是.. 所以你可以使用GetRelativeVector 来设置旋转后的新本地方向

private void OnTriggerEnter2D(Collider2D ball)
{
    // The assignment of the GameObject
    // was kind of redundant except
    // you need the reference for something else later

    var ballRb = ball.GetComponent<Rigidbody2D>();

    // set position through RigidBody component
    ballRb.position = this.transform.position;

    // Rotate the ball using the Rigidbody component
    // Was the int overload intented here? Returning int values 0-359
    // otherwise rather use the float overload by passing float values as parameters
    ballRb.rotation = Random.Range(0f, 360f);

    // Start moving the ball again
    // with a Vector different to Vector2.zero 
    // depending on your setup e.g.
    ballRb.velocity = ballRb.GetRelativeVector(Vector2.right * ballController.bulletSpeed);
}

小演示

顺便说一句,对于墙壁,我使用了非常相似的东西:

var ballRb = ball.GetComponent<Rigidbody2D>();
var newDirection = Vector2.Reflect(ballRb.velocity, transform.up);
ballRb.rotation = ballRb.rotation + Vector2.SignedAngle(ballRb.velocity, newDirection);
ballRb.velocity = newDirection.normalized * ballController.bulletSpeed;

【讨论】:

  • 感谢您提供的信息,我是菜鸟,因此并非您上面所说的所有内容都有意义,您的脚本可以正常工作,但是每次第一次触摸球都会向右反弹,并且只会以随机方向启动它第一次触摸后(指第二次、第三次等)。
  • 嘿,刚刚更新了代码 .. 我对 FixedUpdate 的看法是错误的 .. 当然,碰撞本身已经 is 是 FixedUpdate,因为这已经是物理 ;)
  • 啊,谢谢,我会将您的答案标记为正确,但如果您不介意,我想先问两件事,您能解释一下“int 重载的意图”是什么意思吗在这里?返回 int 值 0-359"?你确定发射方向是完全随机的吗?当我测试它时,我发现它只会向大约 5 个方向发射。
  • @UltraGamer 我很确定它是随机的;)对于RandomRange,请查看链接的 API。有两个版本,一个以int 作为参数,同时返回一个int 值(这里第二个参数是exclusive),另一个以float 值作为参数并返回。如果使用Random.Range(0, 360),则值将始终是完整的int 角度,因此来自0, 1, 2, 3, ... ,359 的随机值。如果使用Random.Range(0f, 360f),角度可以是0-360范围内的任何浮点值,例如0.25f359.888
  • 非常感谢您的解释,我无法使用您答案底部的脚本让墙壁正常工作,但没关系,谢谢!
猜你喜欢
  • 2023-04-05
  • 2018-12-17
  • 1970-01-01
  • 2017-01-11
  • 1970-01-01
  • 2013-09-27
  • 1970-01-01
  • 1970-01-01
  • 2013-01-04
相关资源
最近更新 更多