Button over a in offset texture

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;
	}
}