Jump to content

[SOLVED] PlayerDummy - Camera Movement 360 Collision box (Engine Crash, not opening run)


photo

Recommended Posts

Good evening, I'm new so please have mercy))

Problem: I pointed out the place that results in the program to crash and named it RESULTS IN CRASH. When pressed run, starts running, then closes without opening, but the editor is still open.

Refrence: Reverse engineered the 3rd person platformer demo camera code

Task: I want to add a invisible ObjectStaticMesh box to PlayerDummy and when the box touches something it will change the distanceFromCenter variable so that it will move closer to the player position and won't phase through objects. I'm having problems figuring out how to detect collision. I also want to add movement without it affecting the overall physics on the player variable

 

P.S I understand that there are other cameras, but I always create my own codes because then I know how they function...Refrence aside XD, first time quaternion.

using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;

[Component(PropertyGuid = "1de926e97387c334422e9503b576b68693459c2d")]
public class MeshCameraControl : Component
{
    private PlayerDummy camera;
    public ObjectMeshStatic player;
    public ObjectMeshStatic collisionBox;
  
    private void Init()
    {
        camera = node as PlayerDummy;
        // write here code to be called on component initialization
        Unigine.Console.Run("console_onscreen 1");
        
    }
  
    float xDirection;
    float yDirection;
    float yLimit = 89.9f;
    float distanceFromCenter = 5.0f;
    float turnAngle = 180.0f;
    vec3 direction;
    vec3 rotateAroundX;
    vec3 rotateAroundY;
    private void Update()
    {
  
        xDirection -= Input.MouseDeltaRaw.x;
        yDirection = MathLib.Clamp(yDirection + Input.MouseDeltaRaw.y, -yLimit, yLimit);
  
        rotateAroundX = new quat(vec3.UP, xDirection) * vec3.FORWARD;   
        rotateAroundY = new quat(MathLib.Cross(vec3.UP, rotateAroundX), -yDirection) * rotateAroundX;
        direction = rotateAroundY;
  
        collisionBox.WorldPosition = camera.WorldPosition;
        bool lol = collisionBox.GetCollision(1); (<----------------------------------------------------------RESULTS IN CRASH)
  
        camera.WorldPosition = player.WorldPosition + direction*distanceFromCenter;
        camera.ViewDirection = -direction;
        // write here code to be called before updating each render frame
        quat rotation = new quat(vec3.UP, xDirection + turnAngle);
        player.SetWorldRotation(rotation);
        Log.Message(lol + "\n");
  
    }
}
Link to comment

Noticed that pasting directly from vscode causes problems. I managed to make a collisionbox. It doesn't work perfectly and still phases throgh objects. It needs improvement.

using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;

[Component(PropertyGuid = "1de926e97387c334422e9503b576b68693459c2d")]
public class MeshCameraControl : Component
{
private PlayerDummy camera;
public ObjectMeshStatic player;

private void Init()
{
camera = node as PlayerDummy;
// write here code to be called on component initialization
Unigine.Console.Run("console_onscreen 1");

}

float xDirection;
float yDirection;
float yLimit = 89.9f;
float distanceFromCenter = 5.0f;
float turnAngle = 180.0f;
float height = 1.0f;
vec3 direction;
vec3 rotateAroundX;
vec3 rotateAroundY;
private void Update()
{

vec3 boxMin = camera.WorldPosition - new vec3(0.0f, 0.0f, 1.0f); // Adjust the size of the bounding box as needed
vec3 boxMax = camera.WorldPosition + new vec3(0.0f, 0.0f, 1.0f);
BoundBox boundingBox = new BoundBox(boxMin, boxMax);
List<Unigine.Object> colliders = new List<Unigine.Object>();
List<Unigine.Object> filteredColliders = new List<Unigine.Object>();

bool collisionDetected = Unigine.World.GetCollision(boundingBox, colliders);

foreach (Unigine.Object item in colliders)
{
if (item.Name != "material_ball") {filteredColliders.Add(item);}
}

if (filteredColliders.Count != 0 && distanceFromCenter > 1.0f){distanceFromCenter -= 1;}
if (filteredColliders.Count == 0 && distanceFromCenter < 6.0f){distanceFromCenter += 1;}


xDirection -= Input.MouseDeltaRaw.x;
yDirection = MathLib.Clamp(yDirection + Input.MouseDeltaRaw.y, -yLimit, yLimit);

rotateAroundX = new quat(vec3.UP, xDirection) * vec3.FORWARD;
rotateAroundY = new quat(MathLib.Cross(vec3.UP, rotateAroundX), -yDirection) * rotateAroundX;
direction = rotateAroundY;

camera.WorldPosition = player.WorldPosition + new vec3(0,0,height) + direction*distanceFromCenter;
camera.ViewDirection = -direction;
// write here code to be called before updating each render frame
quat rotation = new quat(vec3.UP, xDirection + turnAngle);
player.SetWorldRotation(rotation);
}
}

 

Edited by Sevdat
Link to comment

Alright, long story short, I just created the Player Persecutor camera. For anyone who finds this instead of Player Dummy just use the Player Persecutor.

Edited by Sevdat
Link to comment
  • silent changed the title to [SOLVED] PlayerDummy - Camera Movement 360 Collision box (Engine Crash, not opening run)

Good day silent,

 I have a question. Why is the movement for rotation smooth when i use Input.MouseDeltaRaw.x but not when I use camera.PhiAngle? How can i make it smooth rotation?

 

using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;

[Component(PropertyGuid = "a95c371ff61b19f210c7b0a9e77741f4f29884c3")]
public class cameraPersecutor : Component
{
	private PlayerPersecutor camera;
	int x;
	int old = 0;
	// public ObjectMeshStatic player;
	private void Init()
	{
		camera = node as PlayerPersecutor;
		// write here code to be called on component initialization
		Unigine.Console.Run("console_onscreen 1");
		x = 0;
		quat rotation = new quat(vec3.UP, 90.0f);
		camera.Target.SetWorldRotation(rotation);
	}
	private void Update()
	{
		// write here code to be called before updating each render frame
		camera.Distance = 5.0f;
		// if (x > 0) x -= 360;
		// if (x < 0) x += 360;
		if ((int)Math.Round(camera.PhiAngle) != old) x += Input.MouseDeltaRaw.x;
		old = (int)Math.Round(camera.PhiAngle);
		// x = (int)Math.Round(camera.PhiAngle);
		quat rotation = new quat(vec3.UP, (float)-x*0.4f);
		camera.Target.SetWorldRotation(rotation);


		Log.Message("phi:" + camera.PhiAngle + "\n");
		Log.Message("x:" + x + "\n");
	}
}

 

Link to comment

Hello!
what purpose are you using 

(int)Math.Round(camera.PhiAngle)

if you want to control phi angle by youself - just set 

player.Fixed = true;

this will turn off the internal logic for changing angles.

 

if you want the target to follow the rotation of the camera, try doing there

vec3 camera_rot = camera.GetWorldDirection();

camera.Target.SetWorldDirection(camera_rot, vec3.UP, MathLib.AXIS.Y)

 

Link to comment

Good day cash-metall,

I want to keep the z axis stable and only rotate left and right. The problem with yours is that it will jitter and not have smooth turns just like getting values from:

camera.PhiAngle

,however this for some reason does have smooth turns.

Input.MouseDeltaRaw.x

  I noticed that the scaling is a bit different too. For example a distance of 5.0f will result in the circumference to be 900 MouseDeltaRaw. That's why I devided 360/900 to equalize the rotation of the material_ball. I'm also trying to make the camera move closer when it interacts with the ground or a wall. Also how can I get the MouseDeltaRaw as a circumference from the distance? That way the mesh will rotate with the camera at equal speeds.

using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;

[Component(PropertyGuid = "a95c371ff61b19f210c7b0a9e77741f4f29884c3")]
public class cameraPersecutor : Component
{
	private PlayerPersecutor camera;
	int x;
	int old = 0;
	// public ObjectMeshStatic player;
	private void Init()
	{
		camera = node as PlayerPersecutor;
		// write here code to be called on component initialization
		Unigine.Console.Run("console_onscreen 1");
		x = 0;
		quat rotation = new quat(vec3.UP, 90.0f);
		camera.Target.SetWorldRotation(rotation);
	}
	float distance = 5.0f;
	private void Update()
	{
		// write here code to be called before updating each render frame
		
		camera.Distance = distance;
		x += Input.MouseDeltaRaw.x;
		quat rotation = new quat(vec3.UP, (float)-x*(360.0f/(900.0f)));
		camera.Target.SetWorldRotation(rotation);

		// x = (int)Math.Round(camera.PhiAngle);
		// camera.Target.SetWorldDirection(vec3.UP, camera_rot, MathLib.AXIS.Z);

		Log.Message("phi:" + old + "\n");
		Log.Message("x:" + x + "\n");
	}
}

With this I wanted to make it so that the MousleDeltaRaw doesn't change when the camera doesn't move because when escape is pressed and the mouse is free, movement makes the object rotate

(int)Math.Round(camera.PhiAngle)
Edited by Sevdat
Link to comment

"jitter" can be caused by the fact that the camera is updated after the nodes. you rotate the object to the camera position in the previous frame. to solve this problem, you can move the update to post-update:

    private void PostUpdate() // after camera update
    {
        if (!camera.Target)
            return;

        var dir = camera.GetWorldDirection(); // get current direction
        dir.z = 0; // ignore z
        if (dir.Length2 != 0)
        {
            dir.Normalize();
            camera.Target.SetWorldDirection(dir, vec3.UP, MathLib.AXIS.Y);
        }

        return;
    }

or force update camera before your logic

private void Update()
    {
        if (!camera.Target)
            return;

        // force update camera
        camera.Controlled = true;
        camera.UpdateControls(Game.IFps);
        camera.FlushTransform();
        camera.Controlled = false;

        var dir = camera.GetWorldDirection();
        dir.z = 0;
        if (dir.Length2 != 0)
        {
            dir.Normalize();
            camera.Target.SetWorldDirection(dir, vec3.UP, MathLib.AXIS.Y);
        }

        return;
    }

 

Link to comment

Good evening cash-metall,

I'm using your code,

using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;

[Component(PropertyGuid = "a95c371ff61b19f210c7b0a9e77741f4f29884c3")]
public class cameraPersecutor : Component
{
	private PlayerPersecutor camera;
	int x;
	int old = 0;
	// public ObjectMeshStatic player;
	private void Init()
	{
		camera = node as PlayerPersecutor;
		// write here code to be called on component initialization
		Unigine.Console.Run("console_onscreen 1");
		x = 0;
		quat rotation = new quat(vec3.UP, 90.0f);
		camera.Target.SetWorldRotation(rotation);
	}
	float distance = 5.0f;
	private void Update()
	{
		// write here code to be called before updating each render frame

 		camera.Distance = 5.0f;
		vec3 camera_rot = camera.GetWorldDirection();

		// camera.Target.SetWorldDirection(vec3.UP, camera_rot, MathLib.AXIS.Z);
        // force update camera
        camera.Controlled = true;
        camera.UpdateControls(Game.IFps);
        camera.FlushTransform();
        camera.Controlled = false;

        var dir = camera.GetWorldDirection();
        dir.z = 0;
        if (dir.Length2 != 0)
        {
            dir.Normalize();
            camera.Target.SetWorldDirection(dir, vec3.UP, MathLib.AXIS.Y);
        }

		Log.Message("phi:" + old + "\n");
		Log.Message("x:" + x + "\n");
	}
}

it works well; however I have problems with detecting collision using the documentation. I made a collisionBox before for Player Dummy which I post again here. The camera moves backward when collision is detected and forward when not detected.

vec3 boxMin = camera.WorldPosition - new vec3(0.0f, 0.0f, 1.0f); // Adjust the size of the bounding box as needed
vec3 boxMax = camera.WorldPosition + new vec3(0.0f, 0.0f, 1.0f);
BoundBox boundingBox = new BoundBox(boxMin, boxMax);
List<Unigine.Object> colliders = new List<Unigine.Object>();
List<Unigine.Object> filteredColliders = new List<Unigine.Object>();

bool collisionDetected = Unigine.World.GetCollision(boundingBox, colliders);

foreach (Unigine.Object item in colliders)
{
if (item.Name != "material_ball") {filteredColliders.Add(item);}
}

if (filteredColliders.Count != 0 && distanceFromCenter > 1.0f){distanceFromCenter -= 1;}
if (filteredColliders.Count == 0 && distanceFromCenter < 6.0f){distanceFromCenter += 1;}

I want to do something similar using Player Persecutor, but by getting the contact point of the camera's collision box. I've already read the documentation:

https://developer.unigine.com/en/docs/latest/objects/players/persecutor/

https://developer.unigine.com/en/docs/2.17/api/library/players/class.playerpersecutor?rlang=cs&words=playerpersecutor#highlight

but when I try to use GetContactPoint from Player Persecutor Class, the engine freezes and crashes. This is what I wrote:

vec3 lol = camera.GetContactPoint(0);

What am I doing wrong? How can I make it better? and how can I understand the documentation better? because although the class pages have the names of the methods, a basic example of how it can be used in programming isn't given under them which makes it hard to understand and use. 

 

Also In the console how can i see the collision boxes? To print messages it's "console_onscreen", but what is the command to show the invisible boxes?

Edited by Sevdat
Link to comment

Hi, Sevdat!

Your program crashes at this line:

vec3 lol = camera.GetContactPoint(0);

because you are trying to get a point that doesn't exist.

First of all check number of contacts and then use them:

// check if the camera has contacts
if (camera.NumContacts > 0)
{
	Log.Message($"Num contacts: {camera.NumContacts}\n");

	// apply some logic for each contact
	for (int i = 0; i < camera.NumContacts; i++)
	{
		vec3 point = camera.GetContactPoint(i);
		// visualizing camera contacts (for example)
		Visualizer.RenderPoint3D(point, 0.1f, vec4.MAGENTA, false, 10);
		Log.Message($"\tContact point: {point.x} {point.y} {point.z}\n");
	}
}

If you want to use camera's boundBox, you can use already existing BoundBox of the camera:

BoundBox bb = camera.BoundBox;
// visualizer shows bb boundBox each frame
Visualizer.RenderBoundBox(bb, camera.WorldTransform, vec4.BLUE);

And if you create boundBox yourself min and max points should be the opposite points of the box diagonal (for example on this pic points B1 and D)

 image.png

More examples with creating BoundBox and finding intersections you can find here.

And if you want to use Visualizer (like in examples for BoundBox and points earlier), you need to enable it first in Init():

Visualizer.Enabled = true;

Best regards!

  • Like 2
Link to comment
×
×
  • Create New...