Unity Navmesh bake multiple maps in the same scene - unity3d

I have an scene with multiple maps, and when the game starts I randomly activate one of the maps and keep the others inactive.
My problem is that I can only have one the maps baked, because when I change to bake other map it's overwrited by the previous bake.
I search for other post to try baking at runtime but is seems it's not possible.
Is there a way to have multiple bakes or to bake only the active map at runtime?

To solve the problem, you can call the bake navigation code after the level changes.
Bake Navigation Inside Unity Editor
This code works similar to what is in the Unity Editor. Just make sure your Navigation Static object is enabled before using it.
The NavMeshBuilder class will allow this. In the code bellow.
using UnityEditor.AI;
...
public void Generate()
{
GenerateLevel(); // for e.g
NavMeshBuilder.BuildNavMesh();
}
Bake Navigation in Runtime
To bake in runtime, you need to download the necessary NavMeshComponents.
The component's will give you a NavMeshSurface component. It does not require static navmesh and works locally. Add component to all of your game ground's then put them in a list as the code bellow. After each run of the game, it is enough to BuildNavMesh all or part of them.
public List<NavMeshSurface> surfaces;
public void Start()
{
GenerateLevel(); // for e.g
surfaces.ForEach(s => s.BuildNavMesh());
}
Also this tutorial from Brackeys will help you so much.

Related

Unity NavmeshComponent (Unable to bake navmesh)

I'm pretty new to Unity and im working on a duo project with my friend. He is generating a city with L-system, with prefabs made in MagicaVoxel, and I'm trying to populate the city with pedestrians and make them walk randomly.
I have the NavMeshComponents from git, and my problem is i can't bake the navmesh on runtime because the objects (roads houses etc.) are instantiated and pieced together on runtime. All the tutorials I've seen had object before running so they could put the navmeshsurface on it, but in this case i can't. Is there a solution for this or i should try to find a different approach? Thanks for the help.
To use the navmesh baking at runtime you need to create a empty GameObject that holds a NavMeshSurface component.
Then in your script, access that component and bake it whenever you need
using Unity.AI.Navigation
void BakeAtRuntime()
{
GetComponent<NavMeshSurface>().BuildNavMesh();
}

How to animate grabbing in Unity VR?

I've been googling this for 10 hours and I'm running out of ideas. I found several video-tutorials and written-tutorials but none of them really works or they're overkill.
I have VR Unity (2020.3.16f) project designed to be run on Quest 2. I'm not using OpenXR. I already created hand, created one simple grabbing animation, added animation to Animator, created transitions, and set "IsGrabbed" parameter. Now I'm looking a simple way to change "IsGrabbed" to true/false whenever I grab/release anything. I'm expecting something like this:
public class grabber : MonoBehaviour
{
// Start is called before the first frame update
Animator animator;
???
void Start()
{
???
}
// Update is called once per frame
void Update()
{
if (???)
{
animator.SetBool("IsGrabbing", true);
}
elseif (???)
{
animator.SetBool("IsGrabbing", false);
}
}
}
Please help. We're talking about VR here so I'm sure grabbing animation is the very basics of very basics of very basics. It can't be any difficult.
Best regards
First of all, I highly recommend watching this video by Justin P Barnett to get a much better overview of how this all works.
If you don't want to go that route for some reason, there are other options available to you. One such option is the "Player Input" component, which can act as a bridge between your input devices and your code. Most XR packages these days use the new Input System package, and it makes life easier, so I will assume you have that installed.
First, you will need to create an Input Actions asset, which can be done in the project pane: right-click -> Create -> Input Actions. There are many tutorials which explain this asset in detail, but here is a simple setup to get you started. Double click on the new asset to open the editing window, and create a new Action Map. In the "Actions" list, create a new action with action type Value, Control Type Axis, and in the dropdown arrow on your new action set the path to the input source. As an example source path, I will use XR Controller -> XR Controller -> XR Controller (Left Hand) -> Optional Controls -> grip. Make sure to click Save Asset before closing the window.
Create a script similar to this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class ControllerInputReceiver : MonoBehaviour {
public void FloatToScale(InputAction.CallbackContext context) {
float val = 0.1f + 0.1f * context.ReadValue<float>();
transform.localScale = new Vector3(val, val, val);
}
}
Create a cube somewhere visible in your scene, and add the Input Action Manager component to it, and drag your created Input Actions asset to its list of Action Assets. Then add the ControllerInputReceiver script. Also on this cube, create a Player Input component and drag your Input Actions asset to its Actions element. Choose your map as the default map and change behavior to Invoke Unity Events. Under the events drop down, you should see an element for the Action you created earlier. Drop your Controller Input Receiver component into this Action and select the FloatToScale function.
In theory it should work at this point. Build the game to your device and see if pulling the grip causes the cube to resize. If it does, then you can replace your Update function with:
void SetGrabbing(InputAction.CallbackContext context) {
animator.SetBool("IsGrabbing", context.ReadValue<float>() > cutoff);
}
If you are still having issues at this point, I really recommend checking out these youtube channels. I only started VR a couple of months ago and learned everything I know so far from these people. JustinPBarnett, VRwithAndrew, ValemVR, LevelUp2020. (Links removed because it kept screwing up my post)
Note, the new input system has button options instead of value/axis options for VR devices. These may be closer to what you want, but I had no luck getting them to work today.
Also note, depending on how you organize your code, you may or may not need the "Input Action Manager" component somewhere in your scene with your input actions asset in its list. It enables your actions for you, without you needing to do this programmatically.
Another solution would be:
Using the OVR plugin and Hands prefab (for left and right), to check whether the rotation of each of the fingers on a specific axis (ex. Z-Axis) falls under a specific range-meaning fingers are grasping/flexed.
By referencing for example the Transform of b_l_index1 , which is the corresponding part of the Index Finger within the model, you can check its local roation every frame and trigger the event of grasping when all fingers are rotated to a specific angle. Subsequently, triggering the animation you need.

How can I change the material of an object from a different scene with a button?

I am new to Unity and to get the hang of the program I tried making the Roll a Ball game from the unity classes and expanding it (Adding levels, a pause menu, etc.). Currently, I am trying to make a menu where you can choose the colour of the ball you control. Trying to search it on Google resulted in a dozen different solutions, none of which were of help. It would be appreciated if someone could help me out.
First you need a reference to ball GameObject (or at least his MeshRenderer component)
public GameObject ball;
Then you need to create a Menu with different buttons that correspond every button to the Material you want, simplified:
public Material newBallMaterial;
To change ball material you have to overwrite his material like this:
ball.GetComponent<MeshRenderer>().material = newBallMaterial;
As derHugo pointed, if the trully problem is to maintain the reference between scenes, try to use DontDestroyOnLoad to maintain objects between scenes. Use it like this:
DontDestroyOnLoad(gameObjectToMaintainTheReference);

Teleport Point: Switch to new scene

I have used the following site to set up the teleportation in my game: https://unity3d.college/2017/05/16/steamvr-locomotion-teleportation-movement/.
As seen from the image, i have inputted 'Location3' as the new scene i would like to teleport to in the build settings. However, when i run the .exe file, i am not able to teleport to a 'Location3' even though I am able to teleport to the other teleport points to a new location in the current scene.
The console logs the "TeleportPoint: Hook up your level loading logic to switch to new scene: Location3".
What you are trying to achieve seems to be a scene change (?)
This can be done using
Application.LoadLevel("Location3");
When you change to this scene you might want to manipulate the position of whatever it is that you want to teleport. This could be achieved by using a static class that does something depending on what scene you are changing too.
I do not recommend to use Application.LoadLevel(), because that function is obsolete and won't be supported in future Unity releases.
You can use:
SceneManager.LoadSceneAsync("NameOfScene");
In order not to keep your Teleportation script from being destroyed you can add the following script to your Teleportation Component.
[Serializable]
public class KeepOnSceneChange : MonoBehaviour {
public void Awake() {
DontDestroyOnLoad(this.gameObject);
}
}
Using this Component your object won't be destroyed when a new scene is loaded and therefor can be used to teleport.

How to change cameras in Unity based on camera coordinates?

I'd like to create a movie in Unity, so I would need several cameras and camerapaths.
On the top of this off course I'd like to change between them. For example if Camerapath1 reaches a significant point with Camera1 then I'd like to change to Camerapath2 with Camera2, etc.
I also have Camera Path Animator asset installed. It's working perfectly when I'm using it with only one camera for several camerapaths but I'm unable to change between maincameras.
I'm a newcomer to Unity. I also know that I should do something like this:
...
camera1.camera.active = false;
camera2.camera.active = true;
...
...but where should I populate these lines? On the top of this, how may I catch the event when a camera on a specific camerapath reaches a particular point?
The way to go would be an animation controller that has all camera as children and controls the active state of all cameras. This provides perfect control over the behaviour.
Create an empty game object, add all cameras as children, add an Animator to the main object with one animation. This animation takes all the camera and set their active state. One extra bonus of this approach is the possibility to call methods as well using the AnimationEvent process. You can still define within the animation for some triggered actions like explosions or movements of objects.
As I said, this give you perfect control since you can define easily actions at specific time.
The downside of it is the rigidity of the process. It may not be as flexible as code, but since you are making a movie, you probably do not need flexibility.
If so, you would have your cameras with a collider and rigidbody (isKinematic true), then you would have some trigger box with a simple script:
public void CameraTrigger:MonoBehaviour{
public GameObject nextCamera;
void OnTriggerEnter(Collider col){
if(col.gameObject.CompareTag("Camera")){
col.gameObject.SetActive(false);
nextCamera.SetActive(true);
}
}
}
Then you drag the camera meant to start next as nextCamera.