I have a World Map texture, I put it in a plane and Im using the material offset to make the right - left movement.
I want to put a button right over a country and make this button follows the offset movement.
How can I make the button follow a specific point in the planes material?
I kinda feel this is not the best approach, so I really appreciate any suggestion.
like a pin on a blueprint eh? interesting way
ofcourse is more (at least for me) easy have a fixed offset, and move the plane relative to the camera put the “pin” as child of the plane and voila!, but seem to be a nice challenge, lets see if we can do it.
I finally had the time to do and test that, sorry the delay
I created a script that attached to a 3d object change the position relative to the offset to the plane behind it.
I also consider texture tiling, so the relative position keeps there even if the tiling isnt 1:1
so, on the creation of the button we need to get te original offset up to the plane, and its relative position to the center of the plane, also I dont know the orientation of the plane reltive to the world axis, so, I had to calculate it using the ughly switch
that you see
if the button is a UIButton on screen space, leave the “pin” who have attached this script as empty gameobject(invisible), and use WorldToScreenPoint to set the UIButton at the same pos
public enum RelativeAxis{X, Y, Z}
public class MappingButton : MonoBehaviour {
public GameObject plane;//the plane
MeshRenderer mapRenderer;
Vector2 startingOffset = Vector2.zero;//the offset when create it
Vector2 mapSize = Vector2.one; //the size of the plane in world space units
Vector2 textTiling;
Vector2 LastOffset = Vector2.zero;
public Vector3 StartingPos = Vector3.zero;
public RelativeAxis FromXAxis = RelativeAxis.X;
public RelativeAxis FromYAxis = RelativeAxis.Y;
void Start(){
//get the pos of the button to the map
Vector3 worldPoint = transform.position;
mapRenderer = plane.transform.GetComponent<MeshRenderer>();
Vector3 mapcube = mapRenderer.bounds.size;
//I dont know what are the 0 axis of your plane so I will check it manually
if(mapcube.x < Mathf.Min(mapcube.y,mapcube.z)){
FromXAxis = RelativeAxis.Y;
FromYAxis = RelativeAxis.Z;
}else if(mapcube.y < Mathf.Min(mapcube.x,mapcube.z))
{
FromXAxis = RelativeAxis.X;
FromYAxis = RelativeAxis.Z;
}
else if (mapcube.z < Mathf.Min(mapcube.x,mapcube.y))
{
FromXAxis = RelativeAxis.X;
FromYAxis = RelativeAxis.Y;
}
//get the relative pos of the point by the plane bounds
GetPlaneSize();
startingOffset = mapRenderer.material.mainTextureOffset;
StartingPos = transform.position;
textTiling = mapRenderer.material.mainTextureScale;
}
void Update(){
//if to just updates on change
if(0.001f<(LastOffset - mapRenderer.material.mainTextureOffset).sqrMagnitude)
transform.position = SetPlanePos (mapRenderer.materials[0].mainTextureOffset);
}
void GetPlaneSize(){
Vector3 mapcube = mapRenderer.bounds.size;
switch (FromXAxis) {
case RelativeAxis.X:
mapSize.x = mapcube.x;
break;
case RelativeAxis.Y:
mapSize.x = mapcube.y;
break;
default:
mapSize.x = mapcube.z;
break;
}
switch (FromYAxis) {
case RelativeAxis.X:
mapSize.y = mapcube.x;
break;
case RelativeAxis.Y:
mapSize.y = mapcube.y;
break;
default:
mapSize.y = mapcube.z;
break;
}
}
Vector3 SetPlanePos(Vector2 CurrentOffset){
Vector3 ret = Vector3.zero;
Vector2 RealOffset = startingOffset - CurrentOffset;
ret = StartingPos;
switch (FromXAxis) {
case RelativeAxis.X:
ret.x -= RealOffset.x*mapSize.x/textTiling.x;
break;
case RelativeAxis.Y:
ret.y -= RealOffset.x*mapSize.x/textTiling.x;
break;
default:
ret.z -= RealOffset.x*mapSize.x/textTiling.x;
break;
}
switch (FromYAxis) {
case RelativeAxis.X:
ret.x = RealOffset.y*mapSize.y/textTiling.y;
break;
case RelativeAxis.Y:
ret.y = RealOffset.y*mapSize.y/textTiling.y;
break;
default:
ret.z = RealOffset.y*mapSize.y/textTiling.y;
break;
}
return ret;
}
}