Unity3d Unity在更新Rigidbody2D';s属性
我试图实现一种让玩家在正方形和圆形之间切换的方法。为了使这项工作正常,我的播放器对象有两个碰撞器,一个圆和一个盒子。在它们之间切换时,我只需禁用一个碰撞器并启用另一个,然后切换当前的精灵。当我从圆切换到正方形时,问题就出现了 我希望正方形能够在地板上滑动,而圆圈应该滚动。为了使开关无缝,我必须重新定向正方形,使其与当前速度对齐,并移除角速度。这似乎是可行的,但是有一小段帧(或帧),其中正方形的旋转与圆在切换之前的旋转相同。这对我来说似乎很奇怪,因为新的旋转和精灵是在代码的同一部分中更改的。这是一段展示这个问题的视频 如果这是由于渲染对象的方式导致的问题,我可以用另一种方法解决。我只是想了解为什么会发生这种情况 切换时将特性从圆形更改为方形的零件的代码段:Unity3d Unity在更新Rigidbody2D';s属性,unity3d,Unity3d,我试图实现一种让玩家在正方形和圆形之间切换的方法。为了使这项工作正常,我的播放器对象有两个碰撞器,一个圆和一个盒子。在它们之间切换时,我只需禁用一个碰撞器并启用另一个,然后切换当前的精灵。当我从圆切换到正方形时,问题就出现了 我希望正方形能够在地板上滑动,而圆圈应该滚动。为了使开关无缝,我必须重新定向正方形,使其与当前速度对齐,并移除角速度。这似乎是可行的,但是有一小段帧(或帧),其中正方形的旋转与圆在切换之前的旋转相同。这对我来说似乎很奇怪,因为新的旋转和精灵是在代码的同一部分中更改的。这是一
else if (Input.GetKeyDown("2"))
{
// Update rotation of box to velocity:
float newAngleRadians = Mathf.Atan2(rb.velocity.y, rb.velocity.x);
float newAngleDegrees = newAngleRadians * 180 / Mathf.PI;
rb.rotation = newAngleDegrees;
rb.angularVelocity = 0;
Debug.Log(rb.rotation);
playerShape = Shape.SQUARE;
spriteRenderer.sprite = spriteArray[1];
circleCollider.enabled = false;
boxCollider.enabled = true;
updateShape = true;
}
将刚体设置为newAngleDegrees后直接记录其角度,表明旋转设置正确,但问题仍然存在
为了以防万一,脚本的完整代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class scr_StateMachine : MonoBehaviour
{
// Types of shapes:
public enum Shape { SQUARE, CIRCLE, TRIANGLE }
// Variables:
public Rigidbody2D rb;
public SpriteRenderer spriteRenderer;
public Sprite[] spriteArray;
public Shape playerShape;
public CircleCollider2D circleCollider;
public BoxCollider2D boxCollider;
private bool updateShape;
void Start()
{
playerShape = Shape.CIRCLE;
updateShape = true;
}
void Update()
{
// Get input for shape change:
if(Input.GetKeyDown("1"))
{
playerShape = Shape.CIRCLE;
spriteRenderer.sprite = spriteArray[0];
circleCollider.enabled = true;
boxCollider.enabled = false;
updateShape = true;
}
else if (Input.GetKeyDown("2"))
{
// Update rotation of box to velocity:
float newAngleRadians = Mathf.Atan2(rb.velocity.y, rb.velocity.x);
float newAngleDegrees = newAngleRadians * 180 / Mathf.PI;
rb.rotation = newAngleDegrees;
rb.angularVelocity = 0;
Debug.Log(rb.rotation);
playerShape = Shape.SQUARE;
spriteRenderer.sprite = spriteArray[1];
circleCollider.enabled = false;
boxCollider.enabled = true;
updateShape = true;
}
// Update movement script's shape:
if (updateShape)
{
GetComponent<scr_Movement>().shape = playerShape;
updateShape = false;
}
}
}
使用系统集合;
使用System.Collections.Generic;
使用UnityEngine;
公共类scr_状态机:单行为
{
//形状类型:
公共枚举形状{正方形、圆形、三角形}
//变量:
公共刚体2d rb;
公共喷壶;
公共精灵[]精灵阵;
公众人物;
公共环路集线器2D环路集线器;
公共boxCollider R2D boxCollider;
私有布尔更新图像;
void Start()
{
playerShape=Shape.CIRCLE;
updateShape=true;
}
无效更新()
{
//获取形状更改的输入:
if(Input.GetKeyDown(“1”))
{
playerShape=Shape.CIRCLE;
spriteRenderer.sprite=spriteArray[0];
circleCollider.enabled=true;
boxCollider.enabled=false;
updateShape=true;
}
else if(Input.GetKeyDown(“2”))
{
//将长方体的旋转更新为速度:
float newAngleRadians=Mathf.Atan2(rb.velocity.y,rb.velocity.x);
浮动新角度度=新角度弧度*180/Mathf.PI;
rb.旋转=新角度度;
rb.角速度=0;
Debug.Log(rb.rotation);
playerShape=Shape.SQUARE;
spriteRenderer.sprite=spriteArray[1];
circleCollider.enabled=false;
boxCollider.enabled=true;
updateShape=true;
}
//更新移动脚本的形状:
if(updateShape)
{
GetComponent().shape=播放者;
updateShape=false;
}
}
}
我认为问题在于刚体
/刚体2d
物理应用于固定时间步长(请参阅)。因此,是的,在强大的设备上,在下一个FixedUpdate
调用开始并更改Rigidbody
/Rigidbody2D
行为之前渲染某些帧肯定是可能的
我想你能做的就是等待下一个FixedUpdate
呼叫的更改,例如使用
公共类scr\U状态机:单行为
{
//形状类型:
公共枚举形状{正方形、圆形、三角形}
//变量:
公共刚体2d rb;
公共喷壶;
公共精灵[]精灵阵;
公众人物;
公共环路集线器2D环路集线器;
公共boxCollider R2D boxCollider;
[Serialized Field]私人scr_运动;
void Start()
{
如果(!\u scrMovement)\u scrMovement=GetComponent();
改变形状(形状.圆);
}
//仍然在更新中获取用户输入
无效更新()
{
//获取形状更改的输入:
if(Input.GetKeyDown(“1”))
{
改变形状(形状.圆);
}
else if(Input.GetKeyDown(“2”))
{
改变形状(形状.正方形);
}
}
私有void ChangeShape(Shape newShape)
{
//如果出现相同的形状,我们已经无事可做了
if(newShape==剧组)返回;
//停止任何已经运行的协同程序,因为我们只想处理FixUpdate调用之前的最后一个输入
// https://docs.unity3d.com/ScriptReference/MonoBehaviour.StopAllCoroutines.html
StopAllCoroutines();
//为新形状启动新的协同程序
//看https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html
Start例程(ChangeShapeInExtFixedUpdate(newShape));
}
私有IEnumerator ChangeShapeInExtFixedUpdate(形状新闻形状)
{
//以防万一,如果同样的形状出现,我们已经无事可做了
if(新闻形态==剧组)产量突破;
//等待下一个FixeUpdate调用
//看https://docs.unity3d.com/ScriptReference/WaitForFixedUpdate.html
返回新的WaitForFixedUpdate();
//现在根据新形状进行所需的更改
circleCollider.enabled=newShape==Shape.CIRCLE;
boxCollider.enabled=newShape==Shape.SQUARE;
交换机(新闻形状)
{
外壳形状.圆形:
spriteRenderer.sprite=spriteArray[0];
打破
case Shape.SQUARE:
//将长方体的旋转更新为速度:
var newAngleRadians=Mathf.Atan2(rb.velocity.y,rb.velocity.x);
//看https://docs.unity3d.com/ScriptReference/Mathf.Rad2Deg.html
纽安格尔度变种