is there any way to extract the "Dress fbx" from "femal 2 fbx" ?
because I want to change the clothes of the avatar in run time so I want to extract the "Dress fbx" and save it in database then in run-time if I click on specific button I want the avatar dress this "Dress fbx". Is this method correct?
EDIT
when I clicked on the button and run this code I get this error
public class DressController:MonoBehaviour
{
[SerializeField] private GameObject dressObj = null;
public void SetDressWithColor(Color color){
this.dressObj.GetComponent<MeshRenderer>().material.color = color;
}
}
this picture for this error
EDIT 2
I deleted the dress mesh from the female fbx using 3dmax, then I imported the female fbx into unity, and tried to add dress mesh to female in run time when I click on button, but the dress didn't put on the female why?, this code that I am using when I click on button
//I set this public variables in the Unity editor
public Mesh mesh = null; //Dress mesh
public Material material = null; //Dress_Diffuse
public Transform t = null; // CC_Base_BoneRoot
public void SetDressWithMesh()
{
var smr = this.dressObj.GetComponent<SkinnedMeshRenderer>();
smr.rootBone = t;
smr.sharedMesh = mesh;
smr.material = material;
}
t is the Root Bone for dress (in my code is "CC_Base_BoneRoot") as showing in the picture
You are most likely not using a fbx at runtime. When you drag the fbx in Unity, it gets converted to a hierarchy of gameobject that contains MeshRenderer and MeshFilter pointing to the meshes and materials. This is what you show in the pic.
When you drag this in a scene, it turns into a game object and this is what you will be dealing with.
In your case you want to affect the dress child object. So first you'd find that one or drag it.
Then it depends whether you want to change the dress mesh or just its material. In the first case, you can affect the shape, in the second case, you can affect the colors and texturing.
public class DressController:MonoBehaviour
{
[SerializeField] private GameObject dressObj = null;
public void SetDressWithColor(Color color){
this.dressObj.GetComponent<SkinnedMeshRenderer>().material.color = color;
}
public void SetDressWithMesh(Mesh mesh, Material material){
var smr = this.dressObj.GetComponent<SkinnedMeshRenderer>()
smr.sharedMesh = mesh;
smr.material = material;
}
}
In the case of a mesh update, you'd need to change the material as well since the UV map and so on will not match anymore.Also, your MeshRenderer may use multi materials.
To sum it up, you would address the MeshRenderer, Material and MeshFilter for your case.
Related
My goal is to draw simple, colored meshes on a Canvas in Unity. I set up a Canvas and chose Render Mode World Space. I then added a GameObject, set its RectTransform, added a CanvasRenderer (later also a MeshFilter and MeshRenderer) and a script to create my mesh. Creating the mesh works fine but i have to major problems. The first is that the lightning does not work correctly when using CanvasRenderer instead of MeshRenderer:
My second problem is that no matter the order in the hierarchy as soon as i add a second object to my canvas (e.g. an image with the color white) my custom mesh and its color are no longer visible. Only the white image.
Here is the script i used. The last few lines are comments or not based on what Renderer i tried.
using UnityEngine;
public class MeshCanvas : MonoBehaviour
{
public Material material;
Mesh mesh;
Vector3[] vertices;
int[] triangles;
float canvasHeigt;
float canvasWidth;
private void Update()
{
canvasHeigt = FindObjectOfType<Canvas>().GetComponent<RectTransform>().rect.height;
canvasWidth = FindObjectOfType<Canvas>().GetComponent<RectTransform>().rect.width;
vertices = new Vector3[]
{
new Vector3(0, 0),
new Vector3(0, canvasHeigt),
new Vector3(canvasWidth, canvasHeigt),
new Vector3(canvasWidth, 0)
};
triangles = new int[]
{
0, 1, 2,
2, 3, 0
};
mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
/*
this.GetComponent<MeshFilter>().mesh = mesh;
this.GetComponent<MeshRenderer>().material = material;
*/
CanvasRenderer cr = this.GetComponent<CanvasRenderer>();
cr.SetColor(Color.black);
cr.materialCount = 1;
cr.SetMaterial(material, 0);
cr.SetMesh(mesh);
}
}
For problem 1: If you just want a normal unlit UI element, you should be using the UI/Default material, not a Standard material.
If you do want lighting, In your Canvas properties, set 'Additional Shader Channels' to 'Everything'. Otherwise lighting will not be calculated correctly. You can use a Standard material in this case, or one of the UI/Lit materials.
As for problem 2, I'm not sure. Unity batches all UI elements together for performance reasons, so maybe setting the mesh directly on the CanvasRenderer is breaking the batching, or maybe it's to do with the material you're using.
If you just want to be able to add your own custom 2D shapes to a Canvas, the better way is to make a class that derives from Graphic or MaskableGraphic and override the OnPopulateMesh method to provide your custom mesh vertices.
The advantages here are that it will behave like any other UI element with all the same parameters etc. and you can add it to the Create GameObject menus to easily add it to your scene.
I'm trying to get all tiles around the player in unity 2d tileset.
What I would like to happen when player presses U I Would like to get all tiles surrounding the player including the one underneath the player or simply the one 1 tile in front of them.
I'm trying to make a farming Game where when the player pulls out an item it will highlight on the tilemap where they are about to place it.
Please note I'm not asking for full code, I just want what ever solution allows me to get tiles near the players position
Edit, found a solution by editing someone elses code but im not sure if there's a better way, if not I would also like this to work based on player rotation currently it places a tile above the player. Code Source https://lukashermann.dev/writing/unity-highlight-tile-in-tilemap-on-mousever/
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Tilemaps;
public class PlayerGrid : MonoBehaviour
{
private Grid grid;
[SerializeField] private Tilemap interactiveMap = null;
[SerializeField] private Tilemap pathMap = null;
[SerializeField] private Tile hoverTile = null;
[SerializeField] private Tile pathTile = null;
public GameObject player;
private Vector3Int previousMousePos = new Vector3Int();
// Start is called before the first frame update
void Start()
{
grid = gameObject.GetComponent<Grid>();
}
// Update is called once per frame
void Update()
{
var px = Mathf.RoundToInt(player.transform.position.x);
var py = Mathf.RoundToInt(player.transform.position.y);
var tilePos = new Vector3Int(px, py, 0);
if (!tilePos.Equals(previousMousePos))
{
interactiveMap.SetTile(previousMousePos, null); // Remove old hoverTile
interactiveMap.SetTile(tilePos, hoverTile);
previousMousePos = tilePos;
}
// Left mouse click -> add path tile
if (Input.GetMouseButton(0))
{
pathMap.SetTile(tilePos, pathTile);
}
// Right mouse click -> remove path tile
if (Input.GetMouseButton(1))
{
pathMap.SetTile(tilePos, null);
}
}
}
try to use the layer field inside the inspector, you can create new Layers inside the Project Manager and there you can easily create Layers like "Background" "Scenery" "Player" "Foreground".. after this you can assign them individually to your Tiles also its important to have different grids otherwise you will not be able to assign different layers to it i hope it worked already
This question already has answers here:
How to pass data (and references) between scenes in Unity
(6 answers)
Closed 1 year ago.
I'm new to working in unity and i don't quite understand how to transfer data between scenes. In my case it's the sprites for my inventory when the player picks up an item. here is the code for the items sprites etc.
public class Items : MonoBehaviour
{
public string ItemName;
public string ItemText;
public int itemInList;
public Sprite itemSprite;
public InventorySlot inventorySlot;
public ItemSprites itemSprites;
public Sprite blueberrySprite;
public Sprite cheesecakeSprite;
public Sprite whitebreadSprite;
public Sprite cookiesSprite;
public void Awake()
{
//DontDestroyOnLoad(this);
}
public void gettingID()
{
GameObject Go = new GameObject();
Go.AddComponent<InventorySlot>();
inventorySlot = Go.GetComponent<InventorySlot>();
inventorySlot.itemID = itemInList;
}
public void ItemList()
{
// Cheesecake
if(itemInList == 1)
{
ItemName = "Cheesecake";
ItemText = "A delishious Juicy Cheesecake";
itemSprite = cheesecakeSprite;
}
// White Bread
if (itemInList == 2)
{
ItemName = "White Bread";
ItemText = "a basic white loaf that smells amazing";
itemSprite = whitebreadSprite;
}
// Cookies
if (itemInList == 3)
{
ItemName = "Cookies";
ItemText = "just plain Chocolatechip cookies, still delishious though";
itemSprite = cookiesSprite;
}
// Blueberries
if (itemInList == 4)
{
ItemName = "Blueberries";
ItemText = "Big juicy yummy blueberries!";
itemSprite = blueberrySprite;
Debug.Log(ItemText);
}
}
it works just fine when I'm in the scene where the script exist but when I try to use it in my new scene the image will turn out white(blank). I guess that is because the gameobject is not set anymore in the new scene, but how do i transfer the set gameobject sprite to a new scene? I now that you can make stuff static but if I read correctly then it doesn't work on gameobjects. and Dontdestroyonload doen't seem to work either cus the script is not attached to a gameobject in the scene.
a) You can make your sprite a static property in your class and you should be able to access it from anywhere in unity. You can make a simple DataHolder class to hold this value and other static values in your Game (It need not be a MonoBehaviour). However, you will need to load them somehow (From resources or AssetBundles) into your static Array
b) Check my Answer here on how to properly persist a GameObject in the Game if you are using DontDestroyOnLoad and have it attached to a GameObject in the scene. This should be a good option to use, considering you already have a MonoBehaviour class. Just attach it to a GameObject and Follow the answer in the link to maintain one correct instance of the Component.
c) Consider using a simple ScriptableObject if you want to save these values across multiple Game Sessions. It is a simple data container that helps you save data Independent of Classes.
Follow this link for Unity's Documentation on ScriptableObjects
I created a pin object by script attached it to a sphere object .
using UnityEngine;
public class InstantiateMarkerPin : MonoBehaviour
{
public float Xpos;
public float Ypos;
public float Zpos;
public GameObject gameObjectPinInstantiate;
// Start is called before the first frame update
private void Start()
{
Xpos = 0.09f;
Ypos = 0.50f;
Zpos = 1.1f;
//The original object, where to instantiate, and the orientation of the new object
GameObject marker = (GameObject)Resources.Load("gameObjectPin");
Vector3 location = new Vector3(Xpos, Ypos, Zpos);
Quaternion rotation = Quaternion.Euler(0, 0, 0);
//The object the script is attached to
GameObject world = this.gameObject;
//Instantiate the prefab
gameObjectPinInstantiate = Instantiate(marker, location, rotation, world.transform);
Debug.Log("InstantiateMarkerPin class : Marker Location 2 :X, Y, Z : " + gameObjectPinInstantiate.transform.position);
}
// Update is called once per frame
private void Update()
{
}
}
This script is attached to the sphere Object .My sphere Object have shader material of earth image (globe).
This Instantiated Prefabs (gameObjectPin) on sphere surface appears on scene but not on game screen ,When I select the camera object in the camera preview also this object does not appear .
Scene view
Scene View when camera is selected
I am new to Unity what should I check or correct to appear my created object on the sphere
basically I am trying to add pins to corresponding country and label it .Similar to the globe on this http://kitsdmcc.com/news
Gameobject is created when Play is clicked on the sphere object
When the Pin Object is selected on play mode
Oh now I see it! What you did was only setting its GIZMO via this menu
which is only displayed in the SceneView.
This has nothing to do with the rendering in the GameView but is just a way for easier seeing and finding certain types of objects in the SceneView since usually they would be invisible if not selected.
From the Glossary:
A graphic overlay associated with a GameObject
in a Scene
, and displayed in the Scene View
. Built-in scene
tools such as the move tool are Gizmos
, and you can create custom Gizmos using textures or scripting. Some Gizmos are only drawn when the GameObject is selected, while other Gizmos are drawn by the Editor regardless of which GameObjects
are selected.
As noted in the comments there is no Component at all on your GameObject so nothing is rendered in the Gameview.
Of course now you could enable Gizmos also for the GameView via the Gizmos toggle
but I guess what you rather are trying to achieve is rather rendering that icon in the final App.
You probably would like to use e.g. the SpriteRenderer component here. And simply drag in your Icon to the Sprite property.
You might have to change the Pin Texture's TextureType to Sprite (2D and UI).
In general I would also recommend to Create a Prefab instead of using the Resources folder here.
There are also some changes I would do to your code in general:
public class InstantiateMarkerPin : MonoBehaviour
{
[Header("Settings")]
// directly use a Vector3 for setting the values
// | default value for this field
// | (only valid until changed via Inspector!)
// v
public Vector3 TargetPosition = new Vector3(0.09f, 0.5f, 1.1f);
// Instead of using Resources simply reference the
// created Prefab here
public GameObject gameObjectPinPrefab;
[Header("Outputs")]
public GameObject gameObjectPinInstantiate;
private void Start()
{
// Careful this currently ovewrites any value set via the
// Inspector. Later you will probably want to remove this.
TargetPosition = new Vector3(0.09f, 0.5f, 1.1f);
//As said I would rather use a prefab here and simply reference it above in the field
//gameObjectPinPrefab = (GameObject)Resources.Load("gameObjectPin");
//Instantiate the prefab
gameObjectPinInstantiate = Instantiate(gameObjectPinPrefab, TargetPosition, Quaternion.identity, transform);
Debug.Log("InstantiateMarkerPin class : Marker Location 2 :X, Y, Z : " + gameObjectPinInstantiate.transform.position);
}
// Always remove empty Unity methods
// They are called as messages if they exist
// and only cause unnecessary overhead
}
I'm trying to add one of my scriptable tiles to my Unity Tilemap during runtime. I can paint the tile in the editor and everything looks fine but I would like to add it during runtime.
I tried instantiating the ScriptableObject asset itself, but it does not have the correct sprites it needs that the generated tile asset has in the editor. Also, I don't believe I should be instantiating the ScriptableObject asset for each tile since one asset is meant to be shared for all of the same tiles on the map.
The Tilemap API provides a way to add a tile, but no instructions or example of how to create the tile.
This is kinda off the top of my head, but I was messing around with something similar yesterday, instantiating a tile on click.
Vector3Int tilePos = map.WorldToCell(mousePos);
YourTileClass tileInstance = ScriptableObject.CreateInstance<YourTileClass>();
Texture2D tex = Resources.Load<Texture2D>("tileTexture") as Texture2D;
Sprite sprite = new Sprite();
sprite = Sprite.Create(tex, new Rect(0, 0, 400, 400), new Vector2(0.5f, 0.5f));
Tile tile = Resources.Load<Tile>("tileInstance") as Tile;
tileInstance .sprite = sprite;
yourTileMap.SetTile(tilePos , tile);
I am not 100% if that is the best way to do it, but it worked for me. Let me know if that does not work and I will double check the actual file.
Sorry, I can't comment, but not knowing what you've tried so far, have you tried assigning the ruletile in the inspector and then just assigning it with SetTile at runtime whenever you need to? From the sounds of it this should achieve what you're trying to do
public Tilemap tilemap;
public MyRuleTile myRuleTile;
tilemap.SetTile(coordinate, myRuleTile);
Assuming your ScriptableObject is inheriting from TileBase object you can do the following:
public Tilemap tilemap;
public TileBase tileToDraw; //Object to draw at runtime
//Get tilemap position from the worldposition
Vector3Int tilemapReferencePosition = tilemap.WorldToCell(reference.transform.position);//this can be the position of another gameObject e.g your Player or MousePosition
roadTileMap.SetTile(tilemapReferencePosition, tileToDraw);
I recently used something similar for a Fire Emblem style RPG where I wanted to draw all the potential directions a spell can be cast before casting it and I ended up with the following function
public void DrawPreAttack(GameObject reference, Spell spell) {
Vector3Int gridReferencePos = preAttackTileMap.WorldToCell(reference.transform.position);
foreach (Vector2 direction in spell.validDirections) {
for (int i = 0; i <= spell.maxDistance; i++) {
preAttackTileMap.SetTile(new Vector3Int(gridReferencePos.x + (i * (int)direction.x) , gridReferencePos.y + (i * (int)direction.y) , 0), preAttackTile);
}
}
}
I have provided two small scripts for you that show you exactly how to do this:
1) The ScriptableObject
After placing this script in the Assets/??? folder, you can create new ScriptableObjects (or rather "ScriptableTiles") by right-clicking in the folder -> ScriptableObjects/ScriptableTile. After you have created such an asset, you have to "fill" it with what you want to have in it. In this case: a Tile. Just drag any Tile from your folder into the "m_Tile" slot that the ScriptableTile provides for you.
using UnityEngine;
using UnityEngine.Tilemaps;
[CreateAssetMenu(fileName = "NewScriptableTile", menuName = "ScriptableObjects/ScriptableTile")]
public class ScriptableTile : ScriptableObject
{
public Tile m_Tile;// Fill this with a Tile
public bool m_IsCollider;// This does nothing, it's just a showcase for what else could be stored in here
}
2) A simple "Placer"
Attach the "Placer" MonoBehaviour to a GameObject and give it a reference to a TileMap and your ScriptableTile. On Start() it will place the Tile in the middle of the chosen TileMap.
using UnityEngine;
using UnityEngine.Tilemaps;
public class ScriptableTilePlacer : MonoBehaviour
{
public Tilemap m_ExampleTileMap;
public ScriptableTile m_ExampleTile;
private void Start()
{
m_ExampleTileMap.SetTile(Vector3Int.zero, m_ExampleTile.m_Tile);
}
}
I've played around with creating TileMaps at runtime myself - you can get even more out of ScriptableTiles by adding more variables. For example, if you have a separate Collider TileMap, you could use a bool to mark certain Tiles as "IsCollider" or "IsNotCollider". Another idea would be to not store Tiles inside the ScriptableTile, but Sprites. This allows you to completely bypass the TilePalette - which is pretty much useless when it comes to runtime creation. Just write a short public Tile GetTileFromSprite() method inside the ScriptableTile. With a few lines of code you can create Tiles from Sprites and return them.