Forge2DGame: No effect setting - body.position.setFrom(info.delta.game) - flame

From this example you can drag around(not at the draggable point but some factor) a BodyComponent by setting body.applyLinearImpulse.
If I try to drag around, setting body.position I get no effect. I was hoping to be able to drag the BodyComponent around at the specific drag point.
Sample code line 37:
#override
bool onDragUpdate(DragUpdateInfo info) {
// final worldDelta = Vector2(1, -1)..multiply(info.delta.game);
// body.applyLinearImpulse(worldDelta * 1000);
body.position.setFrom(info.delta.game);
return false;
}

You should never manipulate body.position directly, since that could break the stability of the physics engine.
For your use-case you probably want to use a MouseJoint instead:
https://github.com/flame-engine/flame/blob/ba617790e4a7ca4dc03f4a2e29de43d42efd3482/packages/flame_forge2d/example/lib/mouse_joint_sample.dart

Related

Converting mouse coordinates for ui in world space

Im having problems with position convertions. The way im trying to solve it may be very wrong but thats due to inexperience in that case and im up for any suggestion on how to do it differently.
What im trying to do is a gui with a dot graph envelope that the user can change by draging the dots with the mouse.
This is what i would wan it to look like.
https://imgur.com/FP6f1Cz
First i did the UI like normal in overlay but i couldnt get the line renderer to work so i took the whole ui into world space. This makes the line renderer visible. With the UI in world space ive tried both to put the envelope line renderer in the canvas with the rest of the ui and outside the canvas UI.
Here is the code that renders the lines where the dots are and moves the dots when the mouse drags them :
public class Envelope : MonoBehaviour
{
LineRenderer lineRenderer;
// Start is called before the first frame update
void Start()
{
lineRenderer = GetComponentInChildren<LineRenderer>();
}
// Update is called once per frame
void Update()
{
var points = GetComponentsInChildren<EnvelopePoint>().Select(ep => ep.transform.localPosition).ToArray();
lineRenderer.positionCount = points.Length;
lineRenderer.SetPositions(points);
}
}
public class EnvelopePoint : MonoBehaviour
{
[SerializeField] bool isHeld = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (isHeld)
{
// Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3 mousePos = Input.mousePosition;
transform.position = mousePos;
}
}
private void OnMouseDown()
{
isHeld = true;
}
private void OnMouseUp()
{
isHeld = false;
}
}
The best result is to put the envelope outside of the canvas.
The lines render well to where the points are but im not able to convert the mouse position to correct coordinates for the dots. When i click on a dot to drag it the dot snaps to a position a bit lower and a bit to the left of the mouse. Like this:
https://imgur.com/3KK6VD3
But then i can drag the dots and the lines adjust perfectly.
I guess i have two questions:
How should i get the mouse position conversion correctly?
Is this a strange or over complicated way of doing this? Is there a more reasonable way?
Id love some tip as well on what i should read up on to better understand the different screen types and how to convert between them.
RectTransformUtility.ScreenPointToWorldPointInRectangle: Transform a screen space point to a position in world space that is on the plane of the given RectTransform.
There is also ScreenPointToLocalPointInRectangle but since you are modifying Line Renderer's points (which are in world space), I think ScreenPointToWorldPointInRectangle best suits your needs.

Unity: Ignore collision of a plateform if jump to it from below. Using ContactFilter & rigidBody.Cast()

I am able to avoid a collision between my player and my entire plateform with the use of contactFilter2D.SetLayerMask() + rigidBody2D.Cast(Vector2, contactFilter, ...);
But I don't find a way to avoid the collision only if my player try to acces to the plateform from below it (with a vertical jump).
I'm pretty sure I should use the contactFilter2D.setNormalAngle() (after specify the minAngle and maxAngle) but no matter the size of my angles, I can't pass threw it.
This is how I initialize my contactFilter2D.
protected ContactFilter2D cf;
void Start () {
cf.useTriggers = false;
cf.minNormalAngle = 0;
cf.maxNormalAngle = 180;
cf.SetNormalAngle(cf.minNormalAngle, cf.maxNormalAngle);
cf.useNormalAngle = true;
}
void Update () {
}
I use it with
count = rb.Cast(move, contactFilter, hitBuffer, distance + shellRadius);
Any ideas ? If you want more code, tell me. But I don't think it will be usefull to understand the matter.
unity actualy has a ready made component for this: it is a physics component called "Platform Effector 2D" if you drag and drop it on your platform it will immediately work the way you want, and it has adjustable settings for tweaking the parameters. hope this helps!

Moving something rotated on a custom pivot Unity

I've created an arm with a custom pivot in Unity which is essentially supposed to point wherever the mouse is pointing, regardless of the orientation of the player. Now, this arm looks weird when pointed to the side opposite the one it was drawn at, so I use SpriteRenderer.flipY = true to flip the sprite and make it look normal. I also have a weapon at the end of the arm, which is mostly fine as well. Now the problem is that I have a "FirePoint" at the end of the barrel of the weapon, and when the sprite gets flipped the position of it doesn't change, which affects particles and shooting position. Essentially, all that has to happen is that the Y position of the FirePoint needs to become negative, but Unity seems to think that I want the position change to be global, whereas I just want it to be local so that it can work with whatever rotation the arm is at. I've attempted this:
if (rotZ > 40 || rotZ < -40) {
rend.flipY = true;
firePoint.position = new Vector3(firePoint.position.x, firePoint.position.y * -1, firePoint.position.z);
} else {
rend.flipY = false;
firePoint.position = new Vector3(firePoint.position.x, firePoint.position.y * -1, firePoint.position.z);
}
But this works on a global basis rather than the local one that I need. Any help would be much appreciated, and I hope that I've provided enough information for this to reach a conclusive result. Please notify me should you need anything more. Thank you in advance, and have a nice day!
You can use RotateAround() to get desired behaviour instead of flipping stuff around. Here is sample code:
public class ExampleClass : MonoBehaviour
{
public Transform pivotTransform; // need to assign in inspector
void Update()
{
transform.RotateAround(pivotTransform.position, Vector3.up, 20 * Time.deltaTime);
}
}

Unity3D OffNavMesh jump issue

I have set up Unity navigation meshes (four planes), navigation agent (sphere) and set up automatic and manual off mesh links. It should now jump between meshes. It does jump between meshes, but it does that in straight lines.
In other words, when agent comes to an edge, instead of actually jumping up (like off mesh link is drawn) it just moves straight in line but a bit faster. I tried moving one plane higher than others, but sphere still was jumping in straight line.
Is it supposed to be like this? Is it possible to set up navigation to jump by some curve? Or should I try to implement that myself?
I came by this question, and had to dig through the Unity sample. I just hope to make it easier for people by extracting the important bits.
To apply your own animation/transition across a navmesh link, you need to tell Unity that you will handle all offmesh link traversal, then add code that regularly checks to see if the agent is on an offmesh link. Finally, when the transition is complete, you need to tell Unity you've moved the agent, and resume normal navmesh behaviour.
The way you handle link logic is up to you. You can just go in a straight line, have a spinning wormhole, whatever. For jump, unity traverses the link using animation progress as the lerp argument, this works pretty nicely. (if you're doing looping or more complex animations, this doesn't work so well)
The important unity bits are:
_navAgent.autoTraverseOffMeshLink = false; //in Start()
_navAgent.currentOffMeshLinkData; //the link data - this contains start and end points, etc
_navAgent.CompleteOffMeshLink(); //Tell unity we have traversed the link (do this when you've moved the transform to the end point)
_navAgent.Resume(); //Resume normal navmesh behaviour
Now a simple jump sample...
using UnityEngine;
[RequireComponent(typeof(NavMeshAgent))]
public class NavMeshAnimator : MonoBehaviour
{
private NavMeshAgent _navAgent;
private bool _traversingLink;
private OffMeshLinkData _currLink;
void Start()
{
// Cache the nav agent and tell unity we will handle link traversal
_navAgent = GetComponent<NavMeshAgent>();
_navAgent.autoTraverseOffMeshLink = false;
}
void Update()
{
//don't do anything if the navagent is disabled
if (!_navAgent.enabled) return;
if (_navAgent.isOnOffMeshLink)
{
if (!_traversingLink)
{
//This is done only once. The animation's progress will determine link traversal.
animation.CrossFade("Jump", 0.1f, PlayMode.StopAll);
//cache current link
_currLink = _navAgent.currentOffMeshLinkData;
//start traversing
_traversingLink = true;
}
//lerp from link start to link end in time to animation
var tlerp = animation["Jump"].normalizedTime;
//straight line from startlink to endlink
var newPos = Vector3.Lerp(_currLink.startPos, _currLink.endPos, tlerp);
//add the 'hop'
newPos.y += 2f * Mathf.Sin(Mathf.PI * tlerp);
//Update transform position
transform.position = newPos;
// when the animation is stopped, we've reached the other side. Don't use looping animations with this control setup
if (!animation.isPlaying)
{
//make sure the player is right on the end link
transform.position = _currLink.endPos;
//internal logic reset
_traversingLink = false;
//Tell unity we have traversed the link
_navAgent.CompleteOffMeshLink();
//Resume normal navmesh behaviour
_navAgent.Resume();
}
}
else
{
//...update walk/idle animations appropriately ...etc
Its recommended to solve your problems via animation. Just create a Jump animation for your object, and play it at the correct time.
The position is relative, so if you increase the Y-position in your animation it will look like the object is jumping.
This is also how the Unity sample is working, with the soldiers running around.
Not sure what version of unity you are using but you could also try this, I know it works just fine in 4:
string linkType = GetComponent<NavMeshAgent>().currentOffMeshLinkData.linkType.ToString();
if(linkType == "LinkTypeJumpAcross"){
Debug.Log ("Yeah im in the jump already ;)");
}
also just some extra bumf for you, its best to use a proxy and follow the a navAgent game object:
Something like:
AIMan = this.transform.position;
AI_Proxy.transform.position = AIMan;
And also be sure to use:
AI_Proxy.animation["ProxyJump"].blendMode = AnimationBlendMode.Additive;
If you are using the in built unity animation!
K, that's my good deed for this week.
Fix position in update()
if (agent.isOnOffMeshLink)
{
transform.position = new Vector3(transform.position.x, 0f, transform.position.z);
}

Andengine 2d side-scroller like mario

I have a question there.
How i make character with gravity and available to walk properly i.e. what functions i need to use and how do i define fixtures? And do i need box2d physics world(i'm using tiled maps)?
So if you can, please tell me how to do 2d side scrolling platformer like mario with andengine.
My code what i'm trying to do :
// Character:
charactersprite = new Sprite(40, 0, this.character);
charactersprite.setScaleX(0.65f);
this.mScene.setOnSceneTouchListener( this);
// PHYSICS
final FixtureDef characterfictur = PhysicsFactory.createFixtureDef(0, 0f,0.5f);
this.mScene.registerUpdateHandler(this.mPhysicsWorld);
final Body body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, charactersprite, BodyType.DynamicBody, characterfictur);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(charactersprite, body, true, false));
mScene.attachChild(charactersprite);
createUnwalkableObjects(mTMXTiledMap);
final PhysicsHandler physicsHandler = new PhysicsHandler(charactersprite);
charactersprite.registerUpdateHandler(physicsHandler);
// HUD
HUD my = new HUD();
Sprite forward = new Sprite( 50, CAMERA_HEIGHT - 170, forwardr){
#Override
public boolean onAreaTouched(TouchEvent pEvent, float pX, float pY){
if(!pEvent.isActionUp()){
charactersprite.getTextureRegion().setFlippedHorizontal(false);
body.setLinearVelocity(new Vector2(CHAR_MOVING_SPEED,body.getLinearVelocity().y)); // Don't look at there
//body.applyLinearImpulse(new Vector2(2,0), body.getPosition());
}else{
//body.applyLinearImpulse(new Vector2(0,0), body.getPosition());
physicsHandler.setVelocity(0, 0);
body.setLinearVelocity(new Vector2(0,body.getLinearVelocity().y)); // Don't look at there
}
return false;
}
};
And little forward :
private void createUnwalkableObjects(TMXTiledMap map){
// Loop through the object groups
for(final TMXObjectGroup group: map.getTMXObjectGroups()) {
//if(group.getTMXObjectGroupProperties().containsTMXProperty("Zeme", "true")){
// This is our "wall" layer. Create the boxes from it
for(final TMXObject object : group.getTMXObjects()) {
final Rectangle rect = new Rectangle(object.getX(), object.getY(),object.getWidth(), object.getHeight());
final FixtureDef boxFixtureDef = PhysicsFactory.createFixtureDef(0, 0,1f);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, rect, BodyType.StaticBody, boxFixtureDef);
rect.setVisible(false);
mScene.attachChild(rect);
}
//}
}
}
So it didn't work properly. So what i'm doing wrong? Please help me.
Thank you very much!
Things you will need:
BoundCamera (to make bounds for your map)
chase entity (your player, so camera will follow your entity)
FixtureDef with little elasticity (to prevent player stopping suddenly on the ground)
create box bodies for your static objects (such as walls and so on)
things like jump - simply use setLinearVelocity
Every 'feature' mentioned above, has its example - simply check and engine examples.
In this thread, I provided some more tips about how to code such game: CLICK