OnActionReceived not being called - c#

I am trying to override the OnActionReceived method of the Agent class. But I don't think that the function is getting called and it doesn't give me any error.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;
public class MoveCar : Agent
{
// more code here
public override void OnActionReceived(ActionBuffers actions)
{
// Get the acceleration, brake, and steer actions from the ML-Agents system
float acceleration = actions.ContinuousActions[0];
float brake = Mathf.Clamp(actions.ContinuousActions[1], 0, 1);
float steer = actions.ContinuousActions[2];
Debug.Log(acceleration);
nowAcceleration = motorMax * acceleration;
nowBrake = brakeMax * brake;
nowSteer = steerMax * steer;
// Apply the actions to the car
wheelBackLeft.motorTorque = nowAcceleration;
wheelBackRight.motorTorque = nowAcceleration;
wheelBackLeft.brakeTorque = nowBrake;
wheelBackRight.brakeTorque = nowBrake;
// wheelFrontLeft.brakeTorque = nowBrake;
// wheelFrontRight.brakeTorque = nowBrake;
wheelFrontLeft.steerAngle = nowSteer;
wheelFrontRight.steerAngle = nowSteer;
updateWheel(wheelFrontLeft, frontLeftTransform);
updateWheel(wheelFrontRight, frontRightTransform);
updateWheel(wheelBackLeft, backLeftTransform);
updateWheel(wheelBackRight, backRightTransform);
}
// more code here
}
I wanted the car to move and to see my acceleration in the Unity3d console but the car does nothing and nothing is printed in the console.

Related

Hello I cant modify Rb.vel.mag in unity

Hello I'm a newbie and I have an error I searched google and there came up results but they used to work I remember but I guess it updated anyway whenever I write this:
m_Rigidbody.velocity.magnitude = m_Max_SpeedBACK;
(Yes, I didn't forget to make the float itself)
And it shows this error
enter image description here
It said I'm not allowed to send img but anyway I want to have this if written simply
(rb.speed = float)
Can anyone help, thanks?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class my_Char_Cont : MonoBehaviour
{
public Rigidbody m_Rigidbody;
public float m_Thrust_Forth = 20f;
public float m_Thrust_Behind = -20f;
public float m_time = 10f;
public float m_timeNeg = -10f;
public float m_Max_SpeedFORTH = 4f;
public float m_Max_SpeedBACK = 2f;
// Start is called before the first frame update
void Start()
{
m_Rigidbody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
bool forwardPress = Input.GetKey("w");
bool backPress = Input.GetKey("s");
bool leftShiftPress = Input.GetKey("left shift");
//---------------------------------------------------------------------------------------------------//
if (forwardPress)
{
m_time = m_time + Time.deltaTime;
if (m_time >= 4)
{
m_time = 3.9f;
}
m_Rigidbody.AddForce(transform.forward * m_Thrust_Forth * m_time);
}
else
{
m_time = 0;
}
if (backPress)
{
m_timeNeg = m_timeNeg + Time.deltaTime;
if (m_timeNeg >= 4)
{
m_timeNeg = 3.9f;
}
m_Rigidbody.AddForce(transform.forward * m_Thrust_Behind * m_timeNeg);
if (m_Rigidbody.velocity.magnitude >= m_Max_SpeedBACK)
{
m_Rigidbody.velocity.magnitude = m_Max_SpeedBACK;
}
}
else
{
m_timeNeg = 0;
}
}
}
The velocity can be read, but not written like that. As #Ruzihm already explained.
If you want to limit the velocity while keeping the direction, do this:
if (m_Rigidbody.velocity.magnitude >= m_Max_SpeedBACK)
{
m_Rigidbody.velocity = m_Rigidbody.velocity.normalized * m_Max_SpeedBACK;
}
normalized returns the vector, normalized so that the length (magnitude) is 1. But to clarify: it is not "(1,1,1)" - the direction stays. Example: (0.802, 0.267, 0.534) has a magnitude of 1.
Therefore, you can assign the velocity to a value, that equals the normalized velocity * your max allowed magnitude.

Why the transform is rotating 360 degrees even if I limit the rotation randomly between specific degrees ranges?

The guns is rotating 360 degrees and not between -40 and 0
This screenshot is the default before running the game the rotation on x is 0 :
and this screenshot is after I changed the guns x rotation value to -40
I want the guns to rotate up down between 0 and -40 but when I'm running the game the guns rotating 360 degrees.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MissleLauncherRotation : MonoBehaviour
{
public Transform body;
public Transform guns;
public Vector3 spinAxisBody;
public Vector3 spinAxisGuns;
public float timeToSpin = 5f;
public float spinSpeed = 20f;
public bool randomSpin = false;
private void Start()
{
StartCoroutine("Spin");
}
private void Update()
{
}
IEnumerator Spin()
{
float spinTimer;
while (true)
{
if (randomSpin == true)
{
spinAxisBody = new Vector3(0,Random.Range(-180, 180),0);
spinAxisGuns = new Vector3(Random.Range(-40, 0), 0, 0);
}
spinTimer = timeToSpin;
while (spinTimer > 0f)
{
body.transform.Rotate(spinAxisBody, Time.deltaTime * spinSpeed);
guns.Rotate(spinAxisGuns, Time.deltaTime * spinSpeed);
spinTimer -= Time.deltaTime;
yield return null;
}
}
}
}
I tried this :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MissleLauncherRotation : MonoBehaviour
{
public Transform body;
public Transform guns;
public Vector3 spinAxisBody;
public Vector3 spinAxisGuns;
public float timeToSpin = 5f;
public float spinSpeed = 20f;
public bool randomSpin = false;
Quaternion rot;
private void Start()
{
rot = guns.rotation;
}
private void Update()
{
guns.Rotate(guns.up, (spinSpeed * Time.deltaTime));
var rot = guns.rotation.eulerAngles;
rot = new Vector3
(
guns.eulerAngles.x,
Mathf.Clamp(rot.x, -40, 0),
guns.eulerAngles.z
);
guns.rotation = Quaternion.Euler(rot);
}
}
The only thing is working now is the clamping but the clamping is not only on the x and I want to use coroutine or somehow to make that it will rotate ever x seconds.
I did it this way to test the clamping if it's working at all now how do I use it with my first code ?
This script is attached to empty gameobject :
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class DronesManager : MonoBehaviour
{
public Transform dronesUnchild;
private List<GameObject> drones = new List<GameObject>();
private static System.Random rnd = new System.Random();
// Start is called before the first frame update
void Start()
{
StartCoroutine(MoveDrone());
}
// Update is called once per frame
void Update()
{
}
private IEnumerator MoveDrone()
{
// same as you did:
var drones = GameObject.FindGameObjectsWithTag("Drone").ToList();
while (drones.Count > 0)
{
// pick one at random, get it
int index = Random.Range(0, drones.Count);
var drone = drones[index];
// remove it from list
drones.RemoveAt(index);
// TODO: might want to check/guard if drone == null ... this guards against it
// being Destroy()ed and yet still lying around in our list marked as "dead"
// simplified your get-component-and-go-if-not-already-going code here
var droneControl = drone.GetComponent<DroneControl>();
if (droneControl.go == false)
{
droneControl.movingSpeed = 5f;
droneControl.go = true;
drone.transform.parent = dronesUnchild;
}
// wait
yield return new WaitForSeconds(0.3f);
}
}
}
And this script is attached to each drone object :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DroneControl : MonoBehaviour
{
public float movingSpeed;
public bool go = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(go)
{
transform.position -= transform.forward * movingSpeed * Time.deltaTime;
}
}
}
Maybe one of this scripts making the problem that it's freezing when trying to change values of variables in the script MissleLauncherRotation ?
As already mentioned Rotate adds a rotation to the current one.
I would rather precalculate the target rotation and use e.g.
public Transform body;
public Transform guns;
public Vector3 spinAxisBody;
public Vector3 spinAxisGuns;
public float timeToSpin = 5f;
public bool randomSpin = false;
// Yes, if you make Start return IEnumerator it is automatically run as a
// Coroutine by Unity without the need for extra code
IEnumerator Start()
{
while (true)
{
// This is the more convenient way of checking for a bool == true
if (randomSpin)
{
spinAxisBody = new Vector3(0,Random.Range(-180, 180),0);
spinAxisGuns = new Vector3(Random.Range(-40, 0), 0, 0);
}
else
{
// whatever you want to happen otherwise
}
// Pre cache/calculate the start and end rotations
// Rotate per default uses the LOCAL space so we will do the same and use localRotation
// But instead of adding to the existing rotation we will use it as a complete new rotation
var startBodyRotation = body.localRotation;
var targetBodyRotation = Quaternion.Euler(spinAxisBody);
var startGunsRotation = guns.localRotation;
var targetGunsRotation = Quaternion.Euler(spinAxisGuns);
// Basically same as the while loop but I prefer to use a for loop so I can't forget to increase the timer
// In my opinion this is simply better readable
for(var spinTimer = 0f; spinTimer < timeToSpin; spinTimer += Time.deltaTime)
{
// Factor linear moving from 0 to 1 within timeToSpin seconds
var factor = spinTimer / timeToSpin;
// optional add ease-in and -out
//factor = Mathf.SmoothStep(0, 1, factor);
// Interpolate linear (or with ease-in and -out) between the pre cached start and end rotations
body.transform.localRotation = Quaternion.Lerp(startBodyRotation, targetBodyRotation, factor);
guns.localRotation = Quaternion.Lerp(startGunsRotation, targetGunsRotation, factor);
yield return null;
}
// Just to be sure to end up with clean values
body.transform.localRotation = targetBodyRotation;
guns.localRotation = targetGunsRotation;
yield return null;
}
}

In my Unity C# game a gameobject is supposed to get thrown but it does absolutely nothing - what's the problem?

I am currently working on an Unity project in C# and my rigidbody isn't moving but I don't get an error. It should get thrown forward and upward but it does nothing - what am I doing wrong here?
Or can it be that my code isn't the problem but I messed something up unn unity?
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public GameObject ThrowObject;
public Canvas StartMenuC, m_SettingsC, m_ShopC;
public Button m_Start, m_Settings, m_Shop, m_CloseShop;
public RawImage m_SettingsImage, m_RTXON, m_RTXOFF;
public Texture m_Texture, m_Texture2;
public Toggle m_RTX;
public Text MoneyText;
string m_ForceXString = string.Empty;
string m_ForceYString = string.Empty;
public Rigidbody rb;
public Transform Forward, Upward;
private Vector3 m_StartPos, m_StartForce;
private Vector3 m_NewForce;
float m_ForceX, m_ForceY;
private int Money = 100;
// Start is called before the first frame update
void Start()
{
// rb = GetComponent<Rigidbody>();
m_NewForce = new Vector3(-5.0f, 1.0f, 0.0f);
m_ForceX = 10;
m_ForceY = 10;
m_ForceXString = "0";
m_ForceYString = "0";
m_StartPos = transform.position;
m_StartForce = rb.transform.position;
m_NewForce = new Vector3(m_ForceX, m_ForceY, 0);
MoneyText = GetComponent<Text>();
m_CloseShop.onClick.AddListener(CloseShop);
m_Settings.onClick.AddListener(Settings);
m_Start.onClick.AddListener(StartGame);
m_Shop.onClick.AddListener(ShopOpen);
m_SettingsImage = GetComponent<RawImage>();
m_SettingsC.enabled = false;
m_ShopC.enabled = false;
m_RTX.onValueChanged.AddListener(delegate {
CheckToggleOn(m_RTX);
});
// PlayerPrefs.SetInt("Money", Money);
// MoneyText.text = "Money: " + Money.ToString() + " $";
}
// Update is called once per frame
void Update()
{
}
void Settings()
{
if (m_SettingsC.enabled == false)
{
m_SettingsC.enabled = true;
}
else
{
m_SettingsC.enabled = false;
}
}
void ShopOpen()
{
m_ShopC.enabled = true;
}
void CloseShop()
{
m_ShopC.enabled = false;
}
private void CheckToggleOn(Toggle change)
{
if (m_RTX.isOn)
{
m_RTXOFF.enabled = false;
m_RTXON.enabled = true;
}
else
{
m_RTXON.enabled = false;
m_RTXOFF.enabled = true;
}
}
private void StartGame()
{
m_SettingsC.enabled = false;
StartMenuC.enabled = false;
m_ShopC.enabled = false;
Instantiate(ThrowObject, new Vector3(0, 356, 26), Quaternion.identity);
Debug.Log("HelloWorld");
if (ThrowObject)
{
Debug.Log("Throw object = true");
rb.AddForce(m_NewForce, ForceMode.Impulse);
}
}
}
What is my error?
And bc of: "It looks like your post is mostly code; please add some more details." and I don't know what else I am supposed to write here I'll tell what the game should look like when done it will be a 3D Mobile Game where you have the objective to throw stuff out of the window I know it's idiotic but its based on a true story from my old school where someone often threw schoolbags out of the window and had to get them back and the school was in the 5. floor
So I guess you want to add force to your newly instantiated "ThrowObject", correct?
However, instead of referencing this object, you add force to "rb", which seemingly is not at all connected to the new object.
Instead, you might want to do something like this:
rb = Instantiate(ThrowObject, new Vector3(0, 356, 26), Quaternion.identity).GetComponent<Rigidbody>();

Start/Update variable scoping

I have a SceneController that's supposed to initialize a set of empty GameObject spawners, each working together at the same rhythm. The RockSpawners receive an array of time delays and wait the X seconds between spawning another rock.
I set the _nextSpawn = float.maxValue when the spawners start and plan to overwrite this after "Initializing" them (my own method), however even though my debug logs say I've overwritten my _nextSpawn value while initializing, the update loop is still reporting float.maxValue and nothing ends up spawning because _timeSinceLastSpawn hasn't exceeded float.maxValue seconds.
Is there something I'm missing with the scope of my _nextSpawn variables? It doesn't seem to be a "this" vs "local" issue, at least at first glance.
Debug output: 0 0 3 3. 0's stay the same, 3's will vary based on rng.
SceneController.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SceneController : MonoBehaviour {
[SerializeField] private GameObject _rockSpawnerPrefab;
public int numRocks = 6;
public int minSpawnDelaySec = 1;
public int maxSpawnDelaySec = 3;
private bool spawnersInitialized = false;
void Start () {
InitializeSpawners();
}
void Update () {
}
void InitializeSpawners() {
float[] pattern = new float[numRocks];
for (int i = 0; i < numRocks; i++) {
// Generate delays at half second increments within bounds
float delay = Mathf.Floor(Random.value * ((float)(maxSpawnDelaySec + 0.5f - minSpawnDelaySec) / 0.5f));
delay = delay * 0.5f + minSpawnDelaySec;
pattern[i] = delay;
}
GameObject spawner = Instantiate(_rockSpawnerPrefab) as GameObject;
spawner.transform.position = new Vector3(0, 4, 0);
RockSpawner rockSpawnerScript = spawner.GetComponent<RockSpawner>();
rockSpawnerScript.Initialize(pattern);
}
}
RockSpawner.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RockSpawner : MonoBehaviour {
[SerializeField] private GameObject _rockPrefab;
public float minSpawnDelay = 3f;
public float maxSpawnDelay = 6f;
private float[] _pattern;
private int _currentPattern;
private float _timeSinceLastSpawn;
private float _nextSpawn;
void Start () {
_currentPattern = -1;
_nextSpawn = float.MaxValue;
}
void Update () {
if (_pattern == null) return;
_timeSinceLastSpawn += Time.deltaTime;
if (_timeSinceLastSpawn > _nextSpawn) {
GameObject rock = Instantiate(_rockPrefab) as GameObject;
rock.transform.position = transform.position;
NextTimer();
}
}
public void Initialize(float[] pattern) {
_pattern = pattern;
NextTimer();
}
private void NextTimer() {
_timeSinceLastSpawn = 0;
_currentPattern += 1;
Debug.Log(_nextSpawn);
Debug.Log(this._nextSpawn);
this._nextSpawn = _pattern[_currentPattern];
Debug.Log(_nextSpawn);
Debug.Log(this._nextSpawn);
}
}
It's not about scoping, it's about call order. When you create a GameObject its Start method is called on the frame it's enabled, not when the object is created. So your code will call Initialize first, then Start which overwrites the values.
Remove the code in Start and handle everything in Initialize and it should work as you want.

Calculating the average of raw data for hand tracking

I have been trying to calculate the average of the raw data that I have been receiving from my camera. The reason is that at the moment I am just using the raw data and this causes quite abit of jitter. Therefore I am wanting the past 5 locations and then an average to be calculated as this would make the hand tracking experience much more smoother.
I have been trying to store the previous 5 locations but when I attempted this I only get the latest raw data which then get stored and overwrites it for the locations.
The OnNewFrame() method is where I get the raw data.
Help on how I would do this would great.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using SDKAttempt;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Drawing;
//The sdk module tracks geometric nodes for every frame
namespace PercUtils
{
class DepthPipeline : UtilMPipeline
{
double screenWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
double screenHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
PXCMGesture.GeoNode nData; //data the we will get from the camera
double xPos = 0;
double yPos = 0;
double zPos = 0;
double handOpeness = 0;
private bool finished;
PXCMGesture.GeoNode[] nodeData = new PXCMGesture.GeoNode[1]; //data from hand
public DepthPipeline()
: base()
{
finished = false;
EnableImage(PXCMImage.ColorFormat.COLOR_FORMAT_DEPTH);
EnableGesture(); //This function is called to enable finger tracking and gesture recognition
}
public override void OnGestureSetup(ref PXCMGesture.ProfileInfo pinfo) //the application can override this function to fine-tune any parameters during module initilisation
{
base.OnGestureSetup(ref pinfo);
}
public override void OnGesture(ref PXCMGesture.Gesture gesture) //the application needs to receive pose/gesture, the application can override the ongesture function
{
if (gesture.label == PXCMGesture.Gesture.Label.LABEL_POSE_THUMB_UP)
{
Console.WriteLine("Thumb Up"); //debug
}
base.OnGesture(ref gesture);
}
public override void OnAlert(ref PXCMGesture.Alert alert) //the application can override the OnAlert function to receive alert notifications
{
base.OnAlert(ref alert);
}
public override bool OnNewFrame()
{
double xRatio = screenWidth / 160; //corrects the ratio of the x axis of the camera to work with the width screen - scales the camera cood for the screen being used
double yRatio = screenHeight / 120; //corrects the ratio of the y axis of the camera to work with the height screen - scales the camera cood for the screen being used
PXCMGesture gesture = QueryGesture();
pxcmStatus sts = gesture.QueryNodeData(0, PXCMGesture.GeoNode.Label.LABEL_BODY_HAND_LEFT, out nData); //gets the status of the left hand, out nData because the value isn't set and the function must set it before returning it
if (sts >= pxcmStatus.PXCM_STATUS_NO_ERROR)
{
xPos = (screenWidth - (nData.positionImage.x * xRatio)) + (screenWidth / 2);
yPos = ((nData.positionImage.y * yRatio) - (screenHeight / 2));
zPos = nData.positionWorld.y * 100;
handOpeness = nData.openness;
TitleScreen.setX(xPos); //this corrects the inverted control of the dot
TitleScreen.setY(yPos);
TitleScreen.getHandOpenness(handOpeness);
PlayGame.setX(xPos); //this corrects the inverted control of the dot
PlayGame.setY(yPos);
PlayGame.getHandOpeness(handOpeness);
PlayGame.getZ(zPos); //gets the z coordnidate of the users hand.
PlayGameEasy.setX(xPos); //this corrects the inverted control of the dot
PlayGameEasy.setY(yPos);
PlayGameEasy.getHandOpeness(handOpeness);
PlayGameEasy.getZ(zPos); //gets the z coordnidate of the users hand.
CollisionClass.setX(xPos);
CollisionClass.setY(yPos);
CollisionClass.getZ(zPos);
Button.setX(xPos);
Button.setY(yPos);
Button.getHandOpeness(handOpeness);
ReplayScreen.getX(xPos);
ReplayScreen.getY(yPos);
HighScore.getX(xPos);
HighScore.getY(yPos);
DifficultyScreen.getX(xPos);
DifficultyScreen.getY(yPos);
}
return !finished;
}
public void Finish()
{
finished = true;
}
public bool IsFinished()
{
return finished;
}
public void StartWork()
{
finished = false;
this.LoopFrames();
}
}
}
Could you add an array of 5 double for each xpos, ypos, zpos and an indexAverage
Make all of them private class variables
In your new frame function use:
Xpos_array [indexAverage]= (screenWidth - (nData.positionImage.x * xRatio)) + (screenWidth / 2);
Xpos = Xpos_array.select(x => x / 5.0).sum();
[.....]
indexAverage = (indexAverage+1)%5;

Categories

Resources