Vector2 has implicit conversion to and from Vector3, but they are not really equivalent, with Vector2 having only X and Y components, while Vector3 has X, Y and Z.
When you try to use someVector3 += someVector2
(or vice-versa), both +=
operators, from Vector3 and Vector2, are valid.
The compiler cannot be sure of which one you want to use, so that exception is it’s way of telling you it can’t safely make a decision, and you need to give it a non-ambiguous set of types to work with. In this case, both sides need to be Vector2 or Vector3; not a mix.
You can do that in 2 ways:
- Working with the compatible type from the start, which is what
@Ruzihm already pointed out in the comments. - Or you can cast the second operand in-place:
transform.position +=
(Vector3)movement * Time.deltaTime * moveSpeed;
Apart from that, I can also see an unhealthy mix of the two types in other portions of the code. I’d strongly suggest you to be consistent. If you are working with 2D, use Vector2s.
Vector2 has it’s own constructor. And the Vector3 constructor with 2 parameters only makes the Z default to zero; it does not create a Vector2.
The only reason it works in the first place is that the compiler is using that implicit conversion I talked about above. That, however, has a performance cost.
rigidbody.AddForce(new Vector
2(0f, 5f), ForceMode2D.Impulse);
Vector2 movement = new Vector
2(value, 0f);
(OrVector
3movement
)
A detail I only learned recently myself is that Unity only syncs Transforms in Update, while movement of a Rigidbody (2D or 3D) is only synced in FixedUpdate. This can cause issues when you set Transform.position
on a Rigidbody’ed object.
And that is one of the reasons why so many sources tell you to «do physics stuff in FixedUpdate». However, while other stuff related to forgetting Time.deltaTime
can happen, as long as the transform and rigidbody are not desynced, you can set position
directly. You do that by using Rigidbody.position
instead of Transform.position
.
An additional nicety of this is that Rigidbody2D.position
is a Vector2, eliminating the need to work with Vector3 or cast for that +=
operation entirely.
public void Move(float value) {
var movement = new Vector2(value, 0f);
rigidbody.position += movement * Time.deltaTime * moveSpeed;
}
One last thing, although it is definitely premature-optimization 🤣 (although not of the bad kind, as it has zero impact on readability in this case), is that you can save a multiplication operation by doing it «vector-last» there: rigidbody.position += Time.deltaTime * moveSpeed * movement
The reason is explained in this other answer.
Asort 1 / 1 / 0 Регистрация: 07.10.2019 Сообщений: 111 |
||||
1 |
||||
07.12.2019, 17:16. Показов 5913. Ответов 1 Метки нет (Все метки)
У меня ошибка в коде и никак она не исправляется! Прошу мне помочь ! код
__________________
0 |
1max1 3088 / 1617 / 921 Регистрация: 26.10.2018 Сообщений: 4,620 |
||||||||
07.12.2019, 17:40 |
2 |
|||||||
Решениелибо
либо
1 |
Identifier Expected (base.ctor)[]
You will often get this error when editing a class constructor. Within the method, you should find a line that looks like:
base..ctor(...);
You need to move this call up next to the constructor signature. So if you have:
public SomeClass(x, y, z) { ... base..ctor(x, y, z); ... }
You should change it to:
public SomeClass(x, y, z) : base(x, y, z) { ... }
The type X already contains a definition for Y[]
(The newest nightly builds of dnSpy no longer have this issue)
Sometimes when editing a class with dnSpy, it will duplicate one or more of the class variables after you compile your changes. This can cause many problems, one of which being when you try to make your next edit, you will get an error because of the duplicate existing.
When you scroll down to the list of class variables, and find the one that was duplicated, the version that is further towards the bottom is the duplicate, while the one further up is the original one.
If the method you modified did not make use of any of the variables that got duplicated, it is safe to just delete the duplicate and continue with your edits. However, if any of those duplicates were present in the modified method, then don’t delete it yet!! If you delete it, the method you modified will get destroyed, and will become something like this:
And if you save the module you will get an error like this:
If this ever happens, use the Undo function to revert your changes immediately, otherwise your DLL will be permanently broken. To avoid this happening, first note the Token hex number that appears over top the duplicate variable, and over top the original variable. Then go back to the method you modified and find every place where the variable is used.
IL Edit those lines. Each of those places will be pointing to the duplicate, so you want to click on them and change them back to the original (you can tell the two apart based on the token numbers). Once you’ve changed all of them back to the original, then you can safely delete the duplicate from the class and continue with your editing.
Cannot convert from X to X[]
(The newest nightly builds of dnSpy no longer have this issue)
This error comes up most often when passing the current class as an argument to another class or function via the «this» keyword. So the lines giving this error will be something like:
this.whatever = new Something(this, x, y, z);
We want to change the «this» keyword temporarily to «null»:
this.whatever = new Something(null, x, y, z);
This will stop the errors and will allow you to compile. However, we can’t leave them as null! We need to change all of those «null» keywords back to «this». This will be done by going back to each of the lines that we changed to null and IL editing them.
In the IL Edit window, the null keyword will appear as «ldnull», you just need to change that to «ldarg.0», and it should become «this» again.
X does not implement interface member Y[]
(The newest nightly builds of dnSpy no longer have this issue)
You may encounter this error when editing C# methods on a class that implements an interface. An interface requires a certain set of methods to be present in the class, but when you are editing a method in C#, the class becomes a «partial class» where all the methods other than the one you are editing get hidden. This triggers the error because the partial class no longer conforms to the interface’s requirements.
If you look up at the signature for the class/partial class, the interfaces will be the ones after the colon that are colored as gray text. Just remove the interface temporarily (make sure you remember what it is called), and you will be able to compile. However, once you’ve compiled the method and are done with your edits, you need to add the interface back!
To do this:
- Right click on the class name.
- Choose «Edit Type».
- Go to the «Interfaces» tab.
- Click «Add…»
- Click «Type»
- Search for the name of the interface you deleted, select it, and click «OK».
The type or namespace name X could not be found[]
This error will appear if you’re missing a using directive. Sometimes when editing a method, dnSpy will fail to copy over all the «using» imports that the class actually contains (found at the very top of the file). Just copy all of the using directives from the original class, and paste them into the Edit Code window, so you don’t miss any.
Operator is ambiguous on operands of type Vector3 and Vector2[]
To solve this, convert the Vector2 in the line that’s throwing an error into a Vector3. For example:
// This will throw an error v2 + v3; // This will compile fine new Vector3(v2.x, v2.y, 0) + v3;
Or in any Other Case…[]
Sometimes there’s some error in the method that you just don’t know how to get around, or it’s just a particularly annoying method to edit because it has a large number of lines that have errors. One good general workaround for many situations is to make a new method with your code changes, then IL edit in a call to the new method into the original method you couldn’t edit with C#. This requires just two IL lines:
ldarg.0 call (reference to your new function)
You can right click in the IL editor to see options for adding new lines/instructions.
I’m making a 2D game with Unity using the new Input System. I used spriteRenderer.flipX
to flip the player but since it is made of three parts (body and two eyes), the spriteRenderer
didn’t work. Also, I couldn’t convert them to a single sprite because I need the eyes in order to animate them. So, I decided to use transform.localscale
for flipping and change movementInput
value from a float to a Vector2. The problem is that when I press the arrow or AD keys to move the character, an error pops up saying «Cannot read value of type Vector2 from composite». This error is from InputActionState
which is a long and complicated code related to the new Input System. Also, getting input from gamepad causes the same error. I don’t know what does this error mean and how can I fix it. Now, the player can jump but it can’t move or flip. You can see the code, the error and my action map down below.
This is my Player Controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
[SerializeField] private float speed, jumpSpeed;
[SerializeField] private LayerMask ground;
private PlayerActionControls playerActionControls;
private Rigidbody2D rb;
private PolygonCollider2D pol;
private Animator animator;
private bool facingRight = true;
private Vector2 movementInput;
private void Awake() {
playerActionControls = new PlayerActionControls();
rb = GetComponent<Rigidbody2D>();
pol = GetComponent<PolygonCollider2D>();
animator = GetComponent<Animator>();
}
private void OnEnable() {
playerActionControls.Enable();
}
private void OnDisable() {
playerActionControls.Disable();
}
void Start()
{
playerActionControls.Land.Jump.performed += ctx => Jump(ctx.ReadValue<float>());
}
private void Jump(float val) {
if (val == 1 && IsGrounded()) {
rb.AddForce(new Vector2(0, jumpSpeed), ForceMode2D.Impulse);
}
}
private bool IsGrounded() {
Vector2 topLeftPoint = transform.position;
topLeftPoint.x -= pol.bounds.extents.x;
topLeftPoint.y += pol.bounds.extents.y;
Vector2 bottomRightPoint = transform.position;
bottomRightPoint.x += pol.bounds.extents.x;
bottomRightPoint.y -= pol.bounds.extents.y;
return Physics2D.OverlapArea(topLeftPoint, bottomRightPoint, ground);
}
void FixedUpdate()
{
if(facingRight == false && movementInput.x > 0){
Flip();
} else if (facingRight == true && movementInput.x < 0){
Flip();
}
}
void Flip(){
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
void Update()
{
movementInput = playerActionControls.Land.Move.ReadValue<Vector2>();
Vector2 currentPosition = transform.position; // This was a Vector3 but since I got the error "Operator '+=' is ambiguous on operands of type 'Vector3' and 'Vector2", I changed it to a Vector2.
currentPosition += movementInput * speed * Time.deltaTime;
transform.position = currentPosition;
}
}
This is the error I get when I want to move the player.
This is my action map.
This is intended behavior. (Section numbers below refer to C# Language Specification 5.0.)
The reason the ulong
/short
comparison is invalid is due to this rule: (§4.1.5 / Integral Types)
For the binary
+
,–
,*
,/
,%
,&
,^
,|
,==
,!=
,>
,<
,>=
, and<=
operators, the operands are converted to typeT
, whereT
is the first ofint
,uint
,long
, andulong
that can fully represent all possible values of both operands.
Emphasis mine. Not all values of short
can be converted to all values of ulong
, so the conversion isn’t permitted.
The reason the ulong
/int.MaxValue
and ulong
/long.MaxValue
comparisons are allowed is due to this one: (§6.1.9 / Implicit constant expression conversions)
An implicit constant expression conversion permits the following conversions:
- A constant-expression (§7.19) of type
int
can be converted to typesbyte
,byte
,short
,ushort
,uint
, orulong
, provided the value of the constant-expression is within the range of the destination type.- A constant-expression of type
long
can be converted to typeulong
, provided the value of the constant-expression is not negative.
There is no rule like this for 16 or 8 bit types.
Additionally, if you modify your code to not use a constant, you can see it no longer compiles:
void Test(ulong ulongValue) { int maxInt = int.MaxValue; if (ulongValue > maxInt) {} // CS0034 }