Rigidbody being accessed from different scripts at the same time - unity3d

I have am using two mixed reality controllers at the same time. The right and left trigger both do different things in my game. The problem is that I can only have one of them access the rigidbody at a time. If the left controller has the script attached it will work correctly. If the right controller has the script attached it will work correctly. But I cannot get both of them to work at the same time. I attached the code below. This script is on both controllers.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR;
public class ControllerRight : MonoBehaviour
{
public GameObject ballObj;
Rigidbody rb;
public SteamVR_Behaviour_Pose pose;
public SteamVR_Input_Sources handType;
public SteamVR_Action_Single clickTrigger;
// Start is called before the first frame update
void Start()
{
rb = ballObj.GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate()
{
Debug.Log("Trigger Status: " + clickTrigger.GetAxis(handType));
if (clickTrigger.GetAxis(handType) > 0.5)
{
rb.velocity = Vector3.forward * clickTrigger.GetAxis(handType) * 10;
}
else if (clickTrigger.GetAxis(handType) == 0)
{
rb.velocity = new Vector3(0, 0, 0);
}
}
}

Instead of setting rigidbody's velocity, try to apply a force in the direction of input. That way, two controllers will not override each other, but result in some combined movement.

Related

2D Instantiated object stops moving when used with timer

Hello I'am trying to make a system that instantiate and object, and the moves it to a set of waypoints. When i use intantiate in the Start() function it travels like intended through the waypoints, but when i add the instantiate line to my update() function it only travels a little while and then stops, the same goes for the rest of the instantiated objects. It has something to do with timer i guess, but i have tried a few approaches, but they all lead to the same thing. Hope someone can help.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class waypointTest : MonoBehaviour
{
[SerializeField] private Transform[] waypoints;
public GameObject waypointInvader;
GameObject go;
private int nextUpdate = 1;
public float speed = 5f;
private int waypointIndex;
void Start()
{
}
void Update()
{
if (Time.time >= nextUpdate)
{
nextUpdate = Mathf.FloorToInt(Time.time) + 1;
go = Instantiate(waypointInvader, transform.position, transform.rotation) as GameObject;
}
if (go.transform.position != waypoints[waypointIndex].transform.position)
{
Vector3 newPos = Vector3.MoveTowards(go.transform.position, waypoints[waypointIndex].transform.position, speed * Time.deltaTime);
go.transform.position = newPos;
if (newPos == waypoints[waypointIndex].transform.position)
{
waypointIndex += 1;
}
if (waypointIndex == waypoints.Length)
{
waypointIndex = 0;
}
}
}
}
The problem is that you are loosing the reference to the object you want to move.
If instantiate is inside Start():
go is set to be the instantiated object
go is moved to every waypoint
go is moved to the very first waypoint
go is moving through the waypoints again
If instantiate is inside Update():
go is set to be the first instantiated object
go is moved to a few waypoints until Time.time >= nextUpdate returns true
go is set to be the second instantiated object and will loose its reference to the first go
The first go stops moving
The second go starts moving
Repeat
One way to solve this problem is to give the moving object go its own movement script. That way you just have to instantiate go and it will handle its movement by itself. If go does not know where the waypoints are you can give it to it after instantiating (For example waypointInvader is a prefab). E.g.:
if (Time.time >= nextUpdate)
{
nextUpdate = Mathf.FloorToInt(Time.time) + 1;
go = Instantiate(waypointInvader, transform.position, transform.rotation) as GameObject;
go.GetComponent<GoMovement>().ListOfWaypoints = waypoints;
}

Struggling to get my animations to work on my first game

I am trying to make my first game and have been struggling to get my animations to work.
I have been following along with a YouTube course and when it came to coding the animations on Unity i cannot seem to get it to work.
Please can someone who understands coding and Unity have a look at the following screenshots and help me out.
This is my code for my game:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float moveSpeed;
private Vector3 input;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Verical"));
Rigidbody.AddForce(input * moveSpeed);
}
}
I cannot get the white dot next to my Player Control script to light up and it will not work.
Any help is appreciated, thanks.
If you are able to change the script, then this is how I would do it:
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
float speed = 10f;
float x = Input.GetAxis(“Horizontal”) * speed * Time.deltaTime;
float z = Input.GetAxis(“Vertical”) * speed * Time.deltaTime;
rb.AddForce(x, 0f, z);
}
And freeze rotation along the x and a axis to not fall over. You can do this in the rigidbody component.

Unity Photon Doesnt Sync

Hey guys I want to make a multiplayer game with unity. But I cannot sync players.
I use Photon Transform View and Photon View. I have attached Photon Transform View to Photon View but still it doesnt work.
This is my player movement code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using Photon.Realtime;
using UnityEngine;
public class Movement : Photon.MonoBehaviour
{
joystick griliVAl;
Animator animasyon;
int Idle = Animator.StringToHash("Idle");
// Use this for initialization
void Start () {
animasyon = GetComponent<Animator>();
griliVAl = GameObject.FindGameObjectWithTag("Joystick").GetComponent<joystick>();
}
public void OnButton()
{
animasyon.Play("attack_01");
}
// Update is called once per frame
void Update () {
float x = griliVAl.griliv.x;
float y = griliVAl.griliv.y;
animasyon.SetFloat("Valx", x);
animasyon.SetFloat("Valy", y);
Quaternion targetRotation = Quaternion.LookRotation(griliVAl.griliv*5);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime);
transform.position += griliVAl.griliv * 5 * Time.deltaTime;
}
}
It will be mobile game. So that these griliVal value is joysticks circle.
But can someone please help me to solve this issue?
If by whatever means it doesn't work, try using OnPhotonSerializeView().
Here is what you can put
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if(stream.isWriting)
stream.SendNext(transform.position);
}
else if(stream.isReading)
{
transform.position = (Vector3)stream.ReceiveNext();
}
}
It is really similar to using Photon transform View, but you are manually synchronizing the player's position.
Check if PhotonView is attached to the same gameobject the script is in for OnPhotonSerializeView to work.
Don't forget to add IPunObservable in your code
public class Movement : Photon.MonoBehaviour, IPunObservable

Unity AnimationEvent has no reciever

Here are the two Error messages I am receiving.
This seems to only happen when the Run animation is playing. Any help would be appreciated.
I am building this game for android and I am using mouse clicks to move the character. Since mouse clicks translate to touch events this should have no barring on the game as far as I know.
I guess I should also note that the animations play fine while playing the game.
'defaultModelfbx' AnimationEvent 'FootL' has no receiver! Are you missing a component?
'defaultModelfbx' AnimationEvent 'FootR' has no receiver! Are you missing a component?
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PlayerController : MonoBehaviour
{
float speed = 10;
float rotSpeed = 5;
Vector3 targetPosition;
Vector3 lookAtTarget;
Quaternion playerRot;
bool moving = false;
Animator thisAnim;
void Update()
{
thisAnim = GetComponent<Animator>();
// Get movement of the finger since last frame
if (Input.GetMouseButton(0))
{
SetTargetPosition();
}
if (moving)
{
Move();
}
}
void SetTargetPosition()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, 1000))
{
targetPosition = hit.point;
lookAtTarget = new Vector3(targetPosition.x - `transform.position.x, 0, targetPosition.z - transform.position.z);`
playerRot = Quaternion.LookRotation(lookAtTarget);
moving = true;
}
}
void Move()
{
thisAnim.SetFloat("speed", 1);
transform.rotation = Quaternion.Slerp(transform.rotation, playerRot, rotSpeed * Time.deltaTime);
transform.position = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.deltaTime);
if (transform.position == targetPosition)
{
moving = false;
thisAnim.SetFloat("speed", 0);
}
}
}
I had the same error, but with a different cause and solution.
All my code was in a (grand)parent gameobject (e.g. WerewolfPlayer) and I wanted to keep it this way. The animator was in a (grand)child gameobject (e.g. WEREWOLF_PBR) and it couldn't find the animation events:
To fix this, I bubbled-up the event from the child gameobject to the parent:
I edited the PlayerController.cs in the parent gameobject (e.g. WerewolfPlayer) to find the new "hand off animation events" script and fire the animation events when they happen:
using UnityEngine;
using System;
public class PlayerController : MonoBehaviour
{
private HandOffAnimationEvent handOffAnimationEvent;
// called when animation event fires
public void Pickup()
{
Debug.Log("player picks up object here...");
}
void OnEnable()
{
handOffAnimationEvent = GetComponentInChildren<HandOffAnimationEvent>();
handOffAnimationEvent.OnPickup += Pickup;
}
void OnDisable()
{
handOffAnimationEvent.OnPickup -= Pickup;
}
}
The new HandOffAnimationEvents.cs was added to the child gameobject (e.g. WEREWOLF_PBR) and when the animation event fires, it fires its own event:
using UnityEngine;
using System;
public class HandOffAnimationEvent : MonoBehaviour
{
public event Action OnPickup;
// This is the animation event, defined/called by animation
public void Pickup()
{
OnPickup?.Invoke();
}
}
Okay thanks to Nathalia Soragge I have found the solution to the problem.
If you look closely at the animation window you can see two white dashes at the top of the time line. I have clicked on one of them in the picture, and sure enough it is one of the events that were throwing the error message.
I am assuming I can just delete these two events since I do not have them anywhere in code. In this case it is looking for the events in my PlayerController since it is attached to my Model defaultModelfbx
UPDATE: I have deleted both events and now everything is running smoothly. Thanks again Nathalia!!!!!!! ;)
If you don't want to listen to any events, you can set Animator.fireEvents to false.
public Animator animator;
void Start()
{
animator.fireEvents = false;
}
https://docs.unity3d.com/ScriptReference/Animator-fireEvents.html
I had the same problem.I solved this by deleting all animation events and recreating all of them again.

Smooth Walking Inside a Sphere

I'm moving a player around the inside of a hollow sphere equipped with a non-convex mesh-collider. The player is meant to walk along the inner surface of the sphere with a gravitational pull towards the ship hull (away from the center). For the gravity, I've attached a modified version of this script to the player:
using UnityEngine;
using System.Collections;
public class Gravity : MonoBehaviour
{
//credit some: podperson
public Transform planet;
public bool AlignToPlanet;
public float gravityConstant = -9.8f;
void Start()
{
}
void FixedUpdate()
{
Vector3 toCenter = planet.position - transform.position;
toCenter.Normalize();
GetComponent<Rigidbody>().AddForce(toCenter * gravityConstant, ForceMode.Acceleration);
if (AlignToPlanet)
{
Quaternion q = Quaternion.FromToRotation(-transform.up, -toCenter);
q = q * transform.rotation;
transform.rotation = Quaternion.Slerp(transform.rotation, q, 1);
}
}
}
Unity's default movement controllers don't seem to work with this Gravity script, so I fashioned a simple one (forward/backward movement only):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
public class NewController : MonoBehaviour {
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
private void FixedUpdate()
{
GetComponent<Rigidbody>().AddForce(transform.forward * CrossPlatformInputManager.GetAxis("Vertical"), ForceMode.Impulse);
}
}
It works in that I'm able to walk around the inside of the sphere. It's very bumpy though, presumably because the forward force causes the player to constantly run into the corners/edges of the sphere polygon, and because these incongruities are not corrected quickly enough by the "AlignToPlanet" Quaternion in the gravity script.
To sum up, I need a way to move smoothly along the inside of the sphere. I'm not sure if this needs to be solved with code or values in the Unity Editor (regard drag, etc.).