SimpleNpc.cs
using Sandbox;

public sealed class SimpleNpc : Component
{
	//In this simple Npc, we will make it so it just follows the closest player!
	//For more information on how this npc is setup, just download the files from my github! (link in my discord)
	//IMPORTANT! MAKE SURE THE NPC GAMEOBJECT IS SET TO NETWORKED GAMEOBJECT WITH AN OWNER!

	//Here we set up some variables
	[Property] public NavMeshAgent Agent {get; set;}
	[Property] public SkinnedModelRenderer Body {get; set;}
	private GameObject CurrentTarget;

	//We need to run this on this, so it does not lag a lot.
	protected override void OnFixedUpdate()
	{
		if (IsProxy) return;

		//We only need this code to run on the owner (i would suggest you make the host the owner or do whatever, i dont care)

		//Here we just make a table of all the gameobjects with the player tag
		var AllPlayers = Scene.FindAllWithTag("player");

		//Make sure closest distance is something big
		var closestDistance = 99999999999999999999999f;
		var CurrentPlayer = GameObject;

		//now we will loop through each one
		//and we will try to find the closest player
		foreach (var player in AllPlayers)
		{
			//We might have ragdolls with the player tag, this ensures that actuall players are calculated
			if (player.Components.Get<PlayerController>() == null) continue;

			//Simple code, just get the distance
			var Distance = Vector3.DistanceBetween(player.WorldPosition, GameObject.WorldPosition);

			//If we are closer than the closest player we have found, update the variables to match the player
			if (Distance < closestDistance)
			{
				//We update the new stuff

				CurrentPlayer = player;
				closestDistance = Distance;
			}
		}

		//This means we found no player. (This will normally not be needed, but it is good to be safe)
		if (CurrentPlayer != GameObject)
		{
			//Now we need to start following!
			CurrentTarget = CurrentPlayer;
			Agent.MoveTo(CurrentTarget.WorldPosition);
		}
	}

	//Now this is a bonus, if you have a animgraph set up inside the body of your npc
	//you can update some variables so animations can work
	//Here is something very simple
	protected override void OnUpdate()
	{
		//This happens regardless of owner or not, because we want all players to see the npc animations
		Body.Set("Velocity", Agent.Velocity.Length);

		//What we are doing here is simple, we are just passing the velocity of the Agent to the animgraph, and then it can 
		//determen if Velocity > 0 = play walking animation, if Velocity = 0 = play idle animation

		if (IsProxy) return;

		//This code will make the npc turn smoothly torwards the direction it is looking
		var TargetRot = Rotation.LookAt(Agent.WishVelocity, Vector3.Up);
		WorldRotation = Rotation.Slerp(WorldRotation, TargetRot, Time.Delta * 8.0f);
	}
}