Best way to make CFrame lookat x% of the destination

Say I had a part (A) that has a LookVector of -0, -0, 1 and another part (B) that had a LookVector of -0, -0, -1, how would I make a part (A) have a LookVector assigned that is 50% (or any other number) of what the LookVector of Part (B) is (with respect to Part A’s original LookVector)?

Here’s my code, it uses Non-Humanoid characters so I have to be specific with the maths, I had a previous implementation that would work, however when a high attackWalkspeed was implemented it would completely bug out and teleport the serverPart to non existent position. This is run constantly in a PreSimulation.

function regular_zombie:walkingLogic(dt:number, moveToPosition:Vector3, distance: number)


	local partWalkingParamas: RaycastParams = self._cModules.logic:createPartWalkingParams(self.instance)
	local partWalkingRaycast: RaycastResult = self._cModules.logic:partWalkingRaycast(
		partWalkingParamas,
		self.serverPart.Position
	)

	local direction: Vector3
	local part: Part = self._cModules.logic:getColliding(self.collidingParams, self.serverPart)

	if not part then -- zombie free to move to position
		direction = (moveToPosition - self.serverPart.Position).Unit * Vector3.new(1,0,1)
	end
	if part then
		direction = (self.serverPart.Position - part.Position).Unit * Vector3.new(1,0,1)
	end



	local _walkToPosition: Vector3 
	local _lookAtDirection: Vector3
	local _finalCFrame: CFrame

	-- if not attackign walking normally
	if self.currentAttackingMove == '' and not self.isAttacking then
		_walkToPosition = self.serverPart.Position + (direction * (self.walkspeed*dt))  
		_lookAtDirection = Vector3.new(
			moveToPosition.X,
			self.serverPart.Position.Y,
			moveToPosition.Z
		)
	end


	-- if attacking then change walkspeed to that of the moves attackspede
	if self.currentAttackingMove ~= '' and self.ATTACKS[self.currentAttackingMove].canMove then


		local attackWalkspeed: number = self.ATTACKS[self.currentAttackingMove].walkspeed
		local rotation: number = self.ATTACKS[self.currentAttackingMove].rotation

		_walkToPosition = self.serverPart.Position + (direction * (attackWalkspeed*dt)) * Vector3.new(1,0,1)


		-- if move has property of rotation then slowly rotate that mob according to the rotation speed
		if rotation and rotation > 0 then


			----///////////////////////////////////////////////
			----///////////////////////////////////////////////
			----///////////////////////////////////////////////
			-- HERE, the previous code I put would often bug out when the attackWalkspeed was too high
			
			--[[local targetDirection = (Vector3.new(moveToPosition.X, self.serverPart.Position.Y, moveToPosition.Z) - self.serverPart.Position).Unit
			local currenDirection = self.serverPart.CFrame.LookVector
			local rotationalStep = math.min(.1, rotation*dt)
			local newDirection = currenDirection:Lerp(targetDirection, rotationalStep)
	

			_walkToPosition = distance < self.M_CONSTANTS.IDLE_THRESHOLD and self.serverPart.Position or self.serverPart.Position + (newDirection * (attackWalkspeed*dt))*Vector3.new(1,0,1)
			_lookAtDirection = (self.serverPart.Position + newDirection)--]]
			
		


		elseif not rotation then

			_lookAtDirection = Vector3.new(
				moveToPosition.X,
				self.serverPart.Position.Y,
				moveToPosition.Z
			)

		elseif rotation <= 0 then

			_lookAtDirection = Vector3.new(
				self.serverPart.Position.X,
				self.serverPart.Position.Y,
				self.serverPart.Position.Z
			)

		end

	end


	if partWalkingRaycast then -- make it so when they walk on a PART they will adjust their Y position to that 
		_walkToPosition = Vector3.new(
			_walkToPosition.X,
			(partWalkingRaycast.Instance.Size.Y/2 + partWalkingRaycast.Instance.Position.Y) + 8.5, -- change this number for everr mob size
			_walkToPosition.Z
		)
	end


	if not self.isWalking and not self.isAttacking then
		_finalCFrame = CFrame.new(
			self.serverPart.Position,
			_lookAtDirection
		)
	else 
		_finalCFrame = CFrame.new(
			_walkToPosition,
			_lookAtDirection
		)
	end
	
	self.serverPart.CFrame = _finalCFrame

end
1 Like
local LookVectorA = Vector3.new(1, 0, 0)
local LookVectorB = Vector3.new(0, 1, 0)

local function getVector(a, b, alpha)
	return (1-alpha)*a + alpha*b 
end

print(getVector(LookVectorA, LookVectorB, 0.5))

I assume you already know how percentages work and how vectors work.
alpha is the percentage
(1 - alpha) is the 100% - x% or in words: the rest percentage needed for 100%

a is the vector everything is gonna be relative to and b is the vector needed for the interpolation between the two

(alpha needs to be between 0 and 1, 0 meaning it is just a’s look vector and 1 meaning it’s just b’s look vector)

Hope this helped!

1 Like

(you just need the function, the rest is for demonstration purpose only)

If you however want to interpolate smoothly between the two I would recommend using the tweenservice in a seperated task.spawn(function() end)

For anyone here looking for something easier to use but harder to understand:

VectorA:Lerp(VectorB, alpha)

it does the same thing

1 Like

Yea idk why it didn’t work with Lerp, weird

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.