Make an Entity look at the Player
You need to understand the following to be able to understand this snippet
Obtaining Vectors
Vector Subtraction
We basically only need to use vector subtraction to get the vector between two vectors/locations.
Vector playerVec = playerToLookAt.getEyeLocation().toVector().clone();
Vector entityVec = entity.getEyeLocation().toVector();
Vector entityToLookAtVec = playerVec.subtract(entityVec);
Then use the obtained vector to set the direction the sheep is facing. There's no need to normalize the vector because spigot will handle that for us.
Location loc = entity.getLocation().setDirection(entityToLookAtVec);
The last step is a formality where we "update" the sheep by teleporting it (but only the direction was changed, so the sheep will only move its head).
entity.teleport(loc);
Here's what we're doing in a 2d example, but it's exactly the same for 3d.

If we render the entityToLookAtVec
in Minecraft it looks just as we expect.

Since the sheep should always look at the player, we need to execute the code every tick. The complete code could is the following.
/**
* Makes an entity (sheep in this example) always look at the player.
*/
public class EntityFacePlayer {
/**
* The java plugin mainly needed to start the scheduler.
*/
private final JavaPlugin plugin;
/**
* The player the entity is going to look at.
*/
private final Player playerToLookAt;
/**
* The bukkit task running as soon as {@link EntityFacePlayer#start(boolean)} is called.
*/
private BukkitTask task;
/**
* Creates an object containing all the necessary information.
* @param playerToLookAt The player the entity is going to look at.
* @param plugin The java plugin mainly needed to start the scheduler.
*/
public EntityFacePlayer(Player playerToLookAt, JavaPlugin plugin) {
this.playerToLookAt = playerToLookAt;
this.plugin = plugin;
}
/**
* Starts the project.
* @param showVisually if interesting vectors should be drawn via the {@link DisplayUtil} class.
*/
public void start(boolean showVisually) {
if(!playerToLookAt.isOnline()) {
return;
}
//spawn in the sheep
LivingEntity entity = playerToLookAt.getWorld().spawn(playerToLookAt.getLocation(), Sheep.class, sheep -> {
sheep.setAI(false);
sheep.setInvulnerable(true);
sheep.setGravity(false);
});
//start a repeating task
Bukkit.getScheduler().runTaskTimer(plugin, bukkitTask -> {
this.task = bukkitTask;
//if anything undesired happened, stop immediately
if(!playerToLookAt.isOnline() || !playerToLookAt.isValid() || !entity.isValid()) {
end();
return;
}
Vector playerVec = playerToLookAt.getEyeLocation().toVector().clone();
Vector entityVec = entity.getEyeLocation().toVector();
Vector entityToLookAtVec = playerVec.subtract(entityVec);
// plot interesting vector
if(showVisually) {
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> DisplayUtil.showVector(entityToLookAtVec, entity.getEyeLocation().toVector(), 15, Color.PURPLE, true, playerToLookAt.getWorld()), 0L);
}
Location loc = entity.getLocation().setDirection(entityToLookAtVec);
entity.teleport(loc);
}, 0L, 1L);
}
/**
* Terminates the project. Cleans up afterwards.
*/
public void end() {
task.cancel();
}
}
Last updated