I've tried a lot of different things. Assigning the array elements just in the editor. Assigning the elements on boot using the Await(). Changing what script calls the functions. What GameObject has the attached script. How the Vector2 is called. How the array is initialized. I can't figure out what I'm missing.
GameRules Script
using System.Collections.Generic;
using UnityEngine;
public class GameRules : MonoBehaviour
{
public GameObject[] rightSwitchSpawns = new GameObject[7];
public GameObject[] leftSwitchSpawns = new GameObject[7];
public GameObject rightSwitchPrefab;
public GameObject leftSwitchPrefab;
void Awake(){
rightSwitchSpawns = GameObject.FindGameObjectsWithTag("RightSpawns");
leftSwitchSpawns = GameObject.FindGameObjectsWithTag("LeftSpawns");
}
// Start is called before the first frame update
void Start()
{
RandomLeft();
RandomRight();
}
public void RandomLeft()
{ Debug.Log("This Left array length is " + leftSwitchSpawns.Length);
int leftRandom1 = Random.Range(0, leftSwitchSpawns.Length -1);
Debug.Log("left 1 index is " + leftRandom1);
Vector2 leftOne = new Vector2(leftSwitchSpawns[leftRandom1].transform.position.x,leftSwitchSpawns[leftRandom1].transform.position.y);
leftSwitchPrefab = Instantiate(leftSwitchPrefab, new Vector2(leftOne.x,leftOne.y), Quaternion.identity);
int leftRandom2 = Random.Range(0, leftSwitchSpawns.Length -1);
while(leftRandom2 == leftRandom1)
{
leftRandom2 = Random.Range(0, leftSwitchSpawns.Length -1);
}
Vector2 leftTwo = new Vector2(leftSwitchSpawns[leftRandom2].transform.position.x,leftSwitchSpawns[leftRandom2].transform.position.y);
leftSwitchPrefab = Instantiate(leftSwitchPrefab, new Vector2(leftTwo.x,leftTwo.y), Quaternion.identity);
Debug.Log("Left 2 index is: " + leftRandom2);
int leftRandom3 = Random.Range(0, leftSwitchSpawns.Length -1);
while(leftRandom3 == leftRandom1 || leftRandom3 == leftRandom2)
{
leftRandom3 = Random.Range(0, leftSwitchSpawns.Length -1);
}
Vector2 leftThree = new Vector2(leftSwitchSpawns[leftRandom3].transform.position.x,leftSwitchSpawns[leftRandom3].transform.position.y);
leftSwitchPrefab = Instantiate(leftSwitchPrefab, new Vector2(leftThree.x,leftThree.y), Quaternion.identity);
Debug.Log("Left 3 index is: " + leftRandom3);
}
public void RandomRight()
{
int rightRandom1 = Random.Range(0, rightSwitchSpawns.Length -1);
Debug.Log("This Right array length is " + rightSwitchSpawns.Length);
Vector2 rightOne = rightSwitchSpawns[rightRandom1].transform.position;
rightSwitchPrefab = Instantiate(rightSwitchPrefab, new Vector2(rightOne.x,rightOne.y), Quaternion.identity);
Debug.Log("Right 1 index is: " + rightRandom1);
int rightRandom2 = Random.Range(0, rightSwitchSpawns.Length -1);
while (rightRandom2 == rightRandom1)
{
rightRandom2 = Random.Range(0, rightSwitchSpawns.Length -1);
}
Vector2 rightTwo = rightSwitchSpawns[rightRandom2].transform.position;
rightSwitchPrefab = Instantiate(rightSwitchPrefab, new Vector2(rightTwo.x,rightTwo.y), Quaternion.identity);
Debug.Log("Right 2 index is: " + rightRandom2);
int rightRandom3 = Random.Range(0, rightSwitchSpawns.Length -1);
while (rightRandom3 == rightRandom1 || rightRandom3 == rightRandom2)
{
rightRandom3 = Random.Range(0, rightSwitchSpawns.Length -1);
}
Vector2 rightThree = rightSwitchSpawns[rightRandom3].transform.position;
rightSwitchPrefab = Instantiate(rightSwitchPrefab, new Vector2(rightThree.x,rightThree.y), Quaternion.identity);
Debug.Log("Right 3 index is: " + rightRandom3);
}
public void DestroyRightSwitches(){
Debug.Log("Right Switches Destroyed");
Destroy(rightSwitchPrefab);
}
public void DestroyLeftSwitches(){
Debug.Log("Left Switches Destroyed");
Destroy(leftSwitchPrefab);
}
}
PlayerMovement Script
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : GameRules
{
private float speed = 5f;
private float jump = 5f;
private Rigidbody2D rb;
private bool isPlaying = false;
private Transform trans;
// Start is called before the first frame update
void Awake()
{
trans = gameObject.GetComponent<Transform>();
rb = gameObject.GetComponent<Rigidbody2D>();
rb.simulated = false;
}
// Update is called once per frame
void Update()
{
if(Input.GetMouseButtonDown(0)){
if(isPlaying == false){
isPlaying = true;
rb.simulated = true;
rb.velocity = new Vector2(speed,0f);
}
else{
rb.velocity = new Vector2(speed,jump);
}
}
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Wall")
{
OnDeath();
}
if(collision.gameObject.tag == "RightSwitch"){
speed = -speed;
rb.velocity = new Vector2(speed,0f);
DestroyRightSwitches();
RandomRight();
}
if(collision.gameObject.tag == "LeftSwitch"){
speed = -speed;
rb.velocity = new Vector2(speed,0f);
DestroyLeftSwitches();
RandomLeft();
}
}
void OnDeath(){
isPlaying = false;
rb.simulated = false;
trans.position = new Vector2(0,0);
DestroyLeftSwitches();
DestroyRightSwitches();
RandomLeft();
RandomRight();
}
}
The specific error is
IndexOutOfRangeException: Index was outside the bounds of the array.
GameRules.RandomLeft () (at Assets/Scripts/GameRules.cs:28)
GameRules.Start () (at Assets/Scripts/GameRules.cs:20)
But if you look at the debug statements. At initial runtime the array is full with a length of 7, Gives you the indexes of each point. and then it runs again for some reason with a length and index of 0. Then the error shows up.
The errors I Get in picture form
Your arrays are declared as public. In Unity3d's MonoBehaviour it means that these fields are serialized. If you have this script attached to the game object on the scene or to some prefab that is instantiated after, serialized values will be taken from this game object (you can see it in the inspector). It means that if there will be empty arrays in the serialized object, the length of your arrays will be 0 at runtime.
The issue is that I have the Playermovement script deriving from my GameRules script so in the hierarchy the player movement script also has empty arrays attached to the game object.
Related
Im using a Grab Object script that grabs a object that is inside the trigger collider.
But when i try to grab a object with more than 1 object inside the collider it grabs all the objects at the same time (example image with two bricks grabbed at the same time).
I need a rule to grab only the nearest object.
two brick grabbed
im using this script to grab the objects.
Found it on a YT tutorial and tweaked it
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PickUp : MonoBehaviour {
public float throwForce = 100;
public bool canHold = true;
public GameObject item;
public GameObject tempParent;
public GameObject poof;
public GameObject vanish;
public GameObject poofParent;
public Transform guide;
public bool isHolding = false;
float distance;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
distance = Vector3.Distance(item.transform.position, guide.transform.position);
if (Input.GetKeyDown("space"))
if (distance <= 6f)
{
isHolding = true;
item.transform.position = tempParent.transform.position;
//Poof
GameObject myPoof = Instantiate(poof, Vector3.zero, Quaternion.identity) as GameObject;
myPoof.transform.parent = poofParent.transform;
myPoof.transform.position = poofParent.transform.position;
Destroy (myPoof, 2);
//Particles
GameObject myVanish = Instantiate(vanish, Vector3.zero, Quaternion.identity) as GameObject;
myVanish.transform.parent = tempParent.transform;
myVanish.transform.position = tempParent.transform.position;
Destroy (myVanish, 4);
}
if (isHolding==true)
{
item.GetComponent<Rigidbody>().useGravity = false;
item.GetComponent<Rigidbody>().detectCollisions = true;
item.GetComponent<Rigidbody>().isKinematic = false;
item.transform.parent = tempParent.transform;
item.transform.position = tempParent.transform.position;
if (Input.GetKeyUp("space"))
{
Debug.Log("Trying to throw");
item.GetComponent<Rigidbody>().AddForce(guide.transform.forward * throwForce);
isHolding = false;
}
}
else
{
item.GetComponent<Rigidbody>().useGravity = true;
item.GetComponent<Rigidbody>().isKinematic = false;
item.transform.parent = null;
}
}
}
There is a sphere cast implemented in Unity's physics system, however it exists for a different purpose. Instead you're looking for Physics.OverlapSphere
Assuming that your guide object should be the center of the sphere you can determine the closest object (closestSelectedObject) in a specified selection radius.
float radiusOfSphere;
float smallesDistance;
Transform closestSelectedObject;
/***/
void Update(){
if(Input.GetKeyDown("space")){
Collider[] hitColliders = Physics.OverlapSphere(guide.transform.position, radiusOfSphere);
if(hitColliders.length > 0){
smallesDistance = radiusOfSphere;
foreach(Collider obj in hitColliders){
float tempDistance = Vector3.Distance(obj.transform.position, guide.transform.position);
if(tempDistance <= smallesDistance){
smallesDistance = tempDistance;
closestSelectedObject = obj;
}
}
/*other stuff that your code does*/
}
}
}
my final functional (Update) code here
Cant make it without your help #derHugo, thank you!
void Update () {
Collider[] hitColliders = Physics.OverlapSphere(guide.transform.position, radiusOfSphere);
var closestSelectedObject = hitColliders.OrderBy(obj => (obj.transform.position - guide.transform.position). sqrMagnitude).FirstOrDefault();
GameObject grabbed = GameObject.Find("grabbedObject");
if (grabbed != null)
{
Debug.Log("existe");
if (Input.GetKeyDown(KeyCode.Space) && !spaceDisabled) {
spaceDisabled = true;
}
}
else
{
if (Input.GetKeyDown("space"))
{
// targetObject does not exist in the scene
Debug.Log("NAOexiste");
if (closestSelectedObject.tag.Contains("CanPickup"))
{
closestSelectedObject.transform.position = tempParent.transform.position;
closestSelectedObject.transform.parent = tempParent.transform;
closestSelectedObject.GetComponent<Rigidbody>().detectCollisions = false;
closestSelectedObject.GetComponent<Rigidbody>().isKinematic = true;
closestSelectedObject.GetComponent<Rigidbody>().useGravity = true;
originalName = closestSelectedObject.name;
closestSelectedObject.name = "grabbedObject";
//Poof
GameObject myPoof = Instantiate(poof, Vector3.zero, Quaternion.identity) as GameObject;
myPoof.transform.parent = poofParent.transform;
myPoof.transform.position = poofParent.transform.position;
Destroy (myPoof, 2);
//Particles
GameObject myVanish = Instantiate(vanish, Vector3.zero, Quaternion.identity) as GameObject;
myVanish.transform.parent = tempParent.transform;
myVanish.transform.position = tempParent.transform.position;
Destroy (myVanish, 4);
}
}
}
if (Input.GetKeyDown(KeyCode.Q))
{
Debug.Log("Q key was pressed.");
grabbed.transform.parent = null;
grabbed.GetComponent<Rigidbody>().detectCollisions = true;
grabbed.GetComponent<Rigidbody>().isKinematic = false;
grabbed.GetComponent<Rigidbody>().useGravity = true;
grabbed.GetComponent<Rigidbody>().AddForce(guide.transform.forward * throwForce);
Input.ResetInputAxes();
grabbed.name = originalName;
}
}
So, when I start the game, my character can jump on the first platform (because that is the manually placed platform), but I cannot jump on the spawned floors. BTW I am able to run on the floors and I know my jump works correctly.
I have tried so many ways of collider detection I am going crazy and I know its a simple fix that I just can't figure out.
I expected my character to be able to jump on the duplicated platforms but the character just doesn't do anything at all.
If anyone is willing to take a look that would be very helpful. - Nick
P.S I know my code is messy.
CODE:
#Code that is on my player script#
using System;
using System.Diagnostics;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using TouchControlsKit;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Text;
using System.IO;
public class Attack : MonoBehaviour
{
const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded
[SerializeField] private LayerMask m_WhatIsGround;
[SerializeField] private Transform m_GroundCheck;
private bool m_Grounded;
public Collider2D objectCollider;
public Collider2D anotherCollider;
[Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f;
private Timer t;
private Timer a;
private float timeStamp;
private float die = 0;
public GameObject bullet;
private bool m_FacingRight = true;
public float move;
private Vector3 velocity = Vector3.zero;
public GameObject idle_0;
public playscript play;
public Transform player;
private Rigidbody2D m_Rigidbody2D;
[SerializeField] private float m_JumpForce = 200f;
bool swing = false;
bool isgrounded = false;
public bool canJump = false;
bool slide = false;
public Transform groundLayer; // Insert the layer here.
public Vector2 jumpHeight;
private Vector2 touchOrigin = -Vector2.one;
public Vector2 moveSpeed;
public bool run;
Collider2D m_Collider;
// variable to hold a reference to our SpriteRenderer component
private SpriteRenderer mySpriteRenderer;
// This function is called just one time by Unity the moment the component loads
private void Awake()
{
// get a reference to the SpriteRenderer component on this gameObject
mySpriteRenderer = GetComponent<SpriteRenderer>();
animator.SetBool("death", false);
}
public Animator animator;
Animator anim;
int swingHash = Animator.StringToHash("swing");
// Use this for initialization
void Start()
{
timeStamp = Time.time + 5;
m_Collider = GetComponent<Collider2D>();
run = false;
m_Rigidbody2D = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
animator.SetBool("isgrounded", false);
isgrounded = false;
canJump = false;
animator.SetBool("swing", false);
}
private void FixedUpdate()
{
m_Grounded = false;
// The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
// This can be done using layers instead but Sample Assets will not overwrite your project settings.
Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].gameObject != gameObject)
animator.SetBool("isgrounded", true);
m_Grounded = true;
}
}
// Update is called once per frame
void Update()
{
anotherCollider = GameObject.FindGameObjectWithTag("Ground").GetComponent<BoxCollider2D>();
objectCollider = GameObject.FindGameObjectWithTag("Player").GetComponent<CapsuleCollider2D>();
Vector3 targetVelocity = new Vector2(move * 2f, m_Rigidbody2D.velocity.y);
m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref velocity, m_MovementSmoothing);
animator.SetBool("run", true);
if (move > 0 && !m_FacingRight)
{
// ... flip the player.
Flip();
}
// Otherwise if the input is moving the player left and the player is facing right...
else if (move < 0 && m_FacingRight)
{
// ... flip the player.
Flip();
}
int horizontal = 0; //Used to store the horizontal move direction.
int vertical = 0; //Used to store the vertical move direction.
#if UNITY_STANDALONE || UNITY_WEBPLAYER
//Check if we are running on iOS, Android, Windows Phone 8 or Unity iPhone
#elif UNITY_IOS || UNITY_ANDROID || UNITY_WP8 || UNITY_IPHONE
//Check if Input has registered more than zero touches
if (Input.touchCount > 0)
{
//Store the first touch detected.
Touch myTouch = Input.touches[0];
//Check if the phase of that touch equals Began
if (myTouch.phase == TouchPhase.Began)
{
//If so, set touchOrigin to the position of that touch
touchOrigin = myTouch.position;
}
//If the touch phase is not Began, and instead is equal to Ended and the x of touchOrigin is greater or equal to zero:
else if (myTouch.phase == TouchPhase.Ended && touchOrigin.x >= 0)
{
//Set touchEnd to equal the position of this touch
Vector2 touchEnd = myTouch.position;
//Calculate the difference between the beginning and end of the touch on the x axis.
float x = touchEnd.x - touchOrigin.x;
//Calculate the difference between the beginning and end of the touch on the y axis.
float y = touchEnd.y - touchOrigin.y;
//Set touchOrigin.x to -1 so that our else if statement will evaluate false and not repeat immediately.
touchOrigin.x = -1;
//Check if the difference along the x axis is greater than the difference along the y axis.
if (Mathf.Abs(x) > Mathf.Abs(y))
//If x is greater than zero, set horizontal to 1, otherwise set it to -1
horizontal = x > 0 ? 1 : -1;
else
//If y is greater than zero, set horizontal to 1, otherwise set it to -1
vertical = y > 0 ? 1 : -1;
}
}
#endif
if (TCKInput.GetAction("jumpBtn", EActionEvent.Up))
{
animator.SetBool("jump", false);
}
if (TCKInput.GetAction("jumpBtn", EActionEvent.Down) && m_Grounded == true)
{
animator.SetBool("jump", true);
m_Grounded = false;
m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
}
if (TCKInput.GetAction("fireBtn", EActionEvent.Down))
{
animator.SetBool("swing", true);
m_Collider.enabled = !m_Collider.enabled;
}
if (TCKInput.GetAction("fireBtn", EActionEvent.Up))
{
animator.SetBool("swing", false);
m_Collider.enabled = !m_Collider.enabled;
}
if (TCKInput.GetAction("slideBtn", EActionEvent.Down))
{
if (timeStamp <= Time.time)
{
animator.SetBool("slide", true);
GameObject b = (GameObject)(Instantiate(bullet, transform.position + transform.right * 1.5f, Quaternion.identity));
b.GetComponent<Rigidbody2D>().AddForce(transform.right * 1000);
timeStamp = Time.time + 5;
}
}
if (TCKInput.GetAction("slideBtn", EActionEvent.Up))
{
animator.SetBool("slide", false);
}
if (TCKInput.GetAction("right", EActionEvent.Press))
{
move = -1;
}
if (TCKInput.GetAction("right", EActionEvent.Up))
{
animator.SetBool("run", false);
}
if (TCKInput.GetAction("left", EActionEvent.Press))
{
move = 1;
}
if (TCKInput.GetAction("left", EActionEvent.Up))
{
animator.SetBool("run", false);
}
if (objectCollider.IsTouching(anotherCollider))
{
canJump = true;
}
else
{
canJump = false;
}
}
private void Flip()
{
// Switch the way the player is labelled as facing.
m_FacingRight = !m_FacingRight;
// Multiply the player's x local scale by -1.
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
void Hurt()
{
move = 4;
SceneManager.LoadScene(0);
}
protected void OnCollisionEnter2D(Collision2D collision)
{
EnemyHealth3 enemy = collision.collider.GetComponent<EnemyHealth3>();
if (enemy != null)
{
move = 0;
animator.SetBool("death", true);
m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
StartCoroutine(ExecuteAfterTime(.1));
}
}
IEnumerator ExecuteAfterTime(double time)
{
yield return new WaitForSeconds((float)time);
Hurt();
}
}
#Code that is on the floor spawner script#
using UnityEngine;
using System.Collections;
public class Floor_Spawn_Script : MonoBehaviour
{
public GameObject[] obj;
private float oldPosition;
private float currentPosition;
private float ctr = 0;
private float inte = 10.19f;
// Use this for initialization
private void Start()
{
oldPosition = transform.position.x;
AddRoom(ctr * inte);
ctr += 1;
AddRoom(ctr * inte);
ctr += 1;
AddRoom(ctr * inte);
}
// Update is called once per frame
void Update()
{
currentPosition = transform.position.x;
if ((currentPosition - oldPosition) <= 9.595f)
{
AddRoom(ctr * inte);
oldPosition = transform.position.x;
ctr += 1;
}
}
void AddRoom(float roomCenter)
{
GameObject room = (GameObject)Instantiate(obj[Random.Range(0, obj.Length)]);
room.transform.position = new Vector3(roomCenter, 0f, 10f);
}
}```
I'm creating a 2d runner and i have this "collision.cs" file that I have my heart system in, I don't get any errors but when I die a heart doesn't get removed so what am I doing wrong?
The system is based on tags so I tried changing the tag system a lot but nothing worked; then I tried to change the way I find the gameobject after a while I saw that it was creating a lot off gameobjects instead of 3 so I tried to change the tag system around that but even that didn't work and I really don't want to have a plain text that says 3 lives etc.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Collision : MonoBehaviour {
public int lifes = 3 ;
//public GameObject Life_icon1;
//public GameObject Life_icon2;
//public GameObject Life_icon3;
public Sprite Heart;
public int current_icon = 3;
public GameObject ParentPanel;
public static int Coins = 0;
public float offset = 150f;
List<int> i = new List<int>() { 1 };
public int tagN;
void Update() {
tagN = i.Max() + 1;
}
// Use this for initialization
void Start () {
for(int x = 0; x < lifes; x++)
{
i.Add(x);
GameObject NewObj = new GameObject(); //Create the GameObject
Image NewImage = NewObj.AddComponent<Image>(); //Add the Image Component script
NewImage.gameObject.tag = x.ToString();
if(x == 0) {
NewImage.transform.position = new Vector3(0 + 40f, 0 + 40f , 0);
} else {
NewImage.transform.position = new Vector3(0 + offset, 0 + 40f , 0);
offset += 130f;
}
//print(x);
NewImage.sprite = Heart; //Set the Sprite of the Image Component on the new GameObject
NewObj.GetComponent<RectTransform>().SetParent(ParentPanel.transform); //Assign the newly created Image GameObject as a Child of the Parent Panel.
NewObj.SetActive(true); //Activate the GameObject
}
}
void AddLife(int amount) {
lifes++;
i.Add(amount);
GameObject NewObj = new GameObject(); //Create the GameObject
NewObj.gameObject.tag = tagN.ToString();
Image NewImage = NewObj.AddComponent<Image>(); //Add the Image Component script
NewImage.transform.position = new Vector3(0 + offset, 0 + 40f , 0);
NewImage.sprite = Heart; //Set the Sprite of the Image Component on the new GameObject
NewObj.GetComponent<RectTransform>().SetParent(ParentPanel.transform); //Assign the newly created Image GameObject as a Child of the Parent Panel.
NewObj.SetActive(true); //Activate the GameObject
}
void DelLife(int amount) {
Vector3 pos = transform.position;
offset -= 130f;
pos.x = -0.49f;
pos.y = -0.49f;
transform.position = pos;
i.RemoveAt(i.Max());
GameObject go = null;
if (GameObject.FindWithTag(tagN.ToString()) != null)
{
go = GameObject.FindWithTag(tagN.ToString());
}
if (go != null)
{
go.gameObject.SetActive(false);
}
}
void OnTriggerEnter2D(Collider2D other)
{
//extra life item collision
if(other.gameObject.name == "Heart_item") {
AddLife(1);
Destroy(other.gameObject);
}
if(other.gameObject.name == "Spike") {
DelLife(1);
}
if(other.gameObject.name == "Coin") {
Destroy(other.gameObject);
Coins += 1;
}
}
}
I have been using Photon unity networking plugin for multiplayer. in the following code for character instantiation I want to spawn the player who joins to be spawned at a fixed point then random. I am new at this and I tried to edit it by giving fixed gameObject position at a button click event but was unable to do so. Here is the code -
using UnityEngine;
public class CharacterInstantiation : OnJoinedInstantiate {
public delegate void OnCharacterInstantiated(GameObject character);
public static event OnCharacterInstantiated CharacterInstantiated;
public new void OnJoinedRoom() {
if (this.PrefabsToInstantiate != null) {
GameObject o = PrefabsToInstantiate[(PhotonNetwork.player.ID - 1) % 4];
//Debug.Log("Instantiating: " + o.name);
Vector3 spawnPos = Vector3.zero;
if (this.SpawnPosition != null) {
spawnPos = this.SpawnPosition.position;
}
Vector3 random = Random.insideUnitSphere;
random = this.PositionOffset * random.normalized;
spawnPos += random;
spawnPos.y = 0;
Camera.main.transform.position += spawnPos;
o = PhotonNetwork.Instantiate(o.name, spawnPos, Quaternion.identity, 0);
if (CharacterInstantiated != null) {
CharacterInstantiated(o);
}
}
}
}
this code is in the test scene with the plugin. Just want to spawn the joining players are fixed point like spawnpoint[0], spawnpoint[1] and so on. Thanks in advance for the help.
and here is the code for prefab instantiate in the plugin-
public class OnJoinedInstantiate : MonoBehaviour
{
public Transform SpawnPosition;
public float PositionOffset = 2.0f;
public GameObject[] PrefabsToInstantiate;
public void OnJoinedRoom()
{
if (this.PrefabsToInstantiate != null)
{
foreach (GameObject o in this.PrefabsToInstantiate)
{
Debug.Log("Instantiating: " + o.name);
Vector3 spawnPos = Vector3.up;
if (this.SpawnPosition != null)
{
spawnPos = this.SpawnPosition.position;
}
Vector3 random = Random.insideUnitSphere;
random.y = 0;
random = random.normalized;
Vector3 itempos = spawnPos + this.PositionOffset * random;
PhotonNetwork.Instantiate(o.name, itempos, Quaternion.identity, 0);
}
}
}
}
If you want to make different spawn points you should change your script to:
using UnityEngine;
public class CharacterInstantiation : OnJoinedInstantiate {
public delegate void OnCharacterInstantiated(GameObject character);
public static event OnCharacterInstantiated CharacterInstantiated;
public int counter = 0;
public Vector3[] spawnPositions;
public new void OnJoinedRoom() {
if (this.PrefabsToInstantiate != null) {
GameObject o = PrefabsToInstantiate[(PhotonNetwork.player.ID - 1) % 4];
//Debug.Log("Instantiating: " + o.name);
Vector3 spawnPos = Vector3.zero;
if (this.SpawnPosition != null) {
spawnPos = spawnPositions[counter];
}
Vector3 random = Random.insideUnitSphere;
random = this.PositionOffset * random.normalized;
spawnPos += random;
spawnPos.y = 0;
Camera.main.transform.position += spawnPos;
o = PhotonNetwork.Instantiate(o.name, spawnPos, Quaternion.identity, 0);
if (CharacterInstantiated != null) {
CharacterInstantiated(o);
counter++;
}
}
}
}
You just need to give values for spawnPositions.
I have a scene in which the player can pick up and drop objects, as well as move and look around.
All player objects are children of an empty game object "MainCharacter":
MainCharacter >
Capsule (With RigidBody and PlayerMoveScript) >
PlayerBase (empty - used for checking if grounded)
MainCamera >
Hands(With PickUpDrop script)
The object I pick up Lerps to my Hands position, however after my capsule collides with any walls there is a strange jittering which I cannot work out how to fix!!
Heres the .exe:GameTest
Heres the data folder : Data
Here are the scripts:
Pick Up and Drop Script:
public bool handsFull = false;
public float distanceMax = 20f;
public Transform handPosition;
public LayerMask canPickUp;
public GameObject taggedGameObject;
public bool colliderTriggered;
public bool bounds;
public PickedUpObject pickedUpScript;
public Rigidbody player;
// Use this for initialization
void Start () {
print(FindClosestPickup().name);
handPosition = transform;
pickedUpScript = null;
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown (KeyCode.E) && !bounds) {
if (Physics.CheckSphere (handPosition.position, 2f, canPickUp)) {
if (handsFull) {
Drop ();
}
if (!handsFull) {
PickedUp ();
}
handsFull = !handsFull;
}
}
if (handsFull) {
RotateMovePickedUpObject();
}
}
private void PickedUp(){
//Closest object to top of list
taggedGameObject = (GameObject)FindClosestPickup();
taggedGameObject.collider.isTrigger = true;
taggedGameObject.rigidbody.useGravity = false;
taggedGameObject.rigidbody.isKinematic = true;
pickedUpScript = taggedGameObject.GetComponent<PickedUpObject> ();
Debug.Log ("Pick Up");
}
private void RotateMovePickedUpObject(){
//Rotate
if(Input.GetKeyDown(KeyCode.End)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(0, 0, 45);
}
if(Input.GetKeyDown(KeyCode.Delete)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(0, 45, 0);
}
if(Input.GetKeyDown(KeyCode.PageDown)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(0, -45, 0);
}
if(Input.GetKeyDown(KeyCode.Home)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(0, 0, -45);
}
if(Input.GetKeyDown(KeyCode.PageUp)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(-45, 0, 0);
}
if(Input.GetKeyDown(KeyCode.Insert)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(45, 0, 0);
}
taggedGameObject.transform.position = Vector3.Lerp(taggedGameObject.transform.position, handPosition.position, (1 - Mathf.Exp( -20 * Time.smoothDeltaTime )) * 10);
}
private void Drop(){
taggedGameObject.collider.isTrigger = false;
taggedGameObject.rigidbody.useGravity = true;
taggedGameObject.rigidbody.isKinematic = false;
taggedGameObject = null;
Debug.Log ("Drop");
pickedUpScript = null;
}
private GameObject FindClosestPickup() {
//Find closest gameobject with tag
GameObject[] gos;
gos = GameObject.FindGameObjectsWithTag("pickup");
GameObject closest = null;
float distance = Mathf.Infinity;
Vector3 position = transform.position;
foreach (GameObject go in gos) {
Vector3 diff = go.transform.position - position;
float curDistance = diff.sqrMagnitude;
if (curDistance < distance) {
closest = go;
distance = curDistance;
}
}
return closest;
}
}
The Picked Up Objects Script:
public PickUpDrop pickUpScript;
public GameObject thisOne;
public Color thecolor;
public bool inObject;
// Use this for initialization
void Start () {
thisOne = this.gameObject;
}
// Update is called once per frame
void Update ()
{
thecolor = thisOne.renderer.material.color;
if (pickUpScript.taggedGameObject != thisOne)
{
gameObject.renderer.material.color = Color.gray;
}
if (pickUpScript.taggedGameObject == thisOne)
{
Color color = renderer.material.color;
color.a = 0.5f;
renderer.material.color = color;
}
}
void OnTriggerEnter ()
{
if (thisOne == pickUpScript.taggedGameObject)
{
inObject = true;
pickUpScript.bounds = true;
gameObject.renderer.material.color = Color.red;
}
}
void OnTriggerExit()
{
if(thisOne == pickUpScript.taggedGameObject)
{
inObject = false;
pickUpScript.bounds = false;
gameObject.renderer.material.color = Color.gray;
}
}
}
taggedGameObject.transform.position = Vector3.Lerp(taggedGameObject.transform.position, handPosition.position, (1 - Mathf.Exp( -20 * Time.smoothDeltaTime )) * 10);
This line will keep moving the object towards the hand's position. If you have a rigidbody attached to the game object you're moving then the physics acting on that object during the physics calculation will conflict with the manual movement of the object during the Update function.
It depends on what you would like to happen when this conflict occurs as to the solution. If you simply want the 'jittering' to stop and still be able to hold objects against other physical objects, then use this;
taggedGameObject.rigidbody.AddForce( ( taggedGameObject.transform.position - handPosition.position ) * force );
This will keep all interactions with the rigidbody. You'll have to tweak the force you move the object with, and perhaps disable gravity on the tagged game object while it's in the players hands. But it should have the desired effect.