As pointed out by @bdecaf's comments, you can write an event handler when z-ticks changes change in order to customize label tags. It uses undocumented functionality .
This is convenient because we still allow MATLAB to automatically select the maximum number of ticks to use depending on the screen space available for the axis, we just adjust the format of the displayed labels.
Example:
function customize_ticks_example() % data [adj,XYZ] = bucky; [r,c] = find(adj); edges = [rc]; points = XYZ'; e = edges'; e(end+1,:) = 1; e = e(:); p = points(:,e); p(:,3:3:end) = NaN; % plot hFig = figure; line(p(1,:), p(2,:), p(3,:), ... 'LineWidth',2, 'Marker','.', 'MarkerSize',20); ax = handle(gca); view(3), grid on, box on xlabel x, ylabel y, zlabel z rotate3d on % listen to changes on ZTick property ev = handle.listener(ax, findprop(ax,'ZTick'), ... 'PropertyPostSet', @onZTickChange); setappdata(hFig, 'my_ztick_listener', ev); end function onZTickChange(~,e) % get the new 'ZTick', and format them as needed labels = num2str(e.NewValue(:),'%g $'); % update the 'ZTickLabel' set(double(e.AffectedObject), 'ZTickLabel',labels) end

Of course, labels do not have to be numerical, you can use any custom labels if you have some scale at which you can interpolate the values ββto determine which label to use.
EDIT:
easier way to install an event listener :
ev = addlistener(gca, 'ZTick', 'PostSet', @onZTickChange);
(in this case, there is no need to store ev inside the GUI using setappdata . This syntax connects the listener to the life cycle of the GUI object).
EDIT 2:
In response to the comments, here is another example:
function example_manual_ticks %% some 3d plot hFig = figure; sphere view(3), grid on, box on xlabel x, ylabel y, zlabel z %% create a hidden copy of the axis hax1 = gca; hax2 = copyobj(hax1, hFig); set(hax2, 'Visible','off', 'Color','none', 'HitTest','off', ... 'XLimMode','manual', 'YLimMode','manual', 'ZLimMode','manual') delete(get(hax2, 'Children')) uistack(hax2, 'bottom') % sync axes on 3d rotation hlink = linkprop([hax1,hax2], {'CameraPosition','CameraUpVector'}); setappdata(hax1, 'my_axes_linkprop', hlink); rotate3d on % respnd to changes in ZTick axis property ev = addlistener(hax2, 'ZTick', 'PostSet',@(o,e) onZTickChange(o,e,hax1)); %% animation el = 90 .* sin(linspace(0,2*pi,100) + asin(1/3)); for n=1:numel(el) view(-37.5, el(n)) drawnow end end
function onZTickChange(~,e,ax) % determine number of ticks num_ticks = numel(e.NewValue); new_num_ticks = num_ticks - 1; % interpolate new ticks along the axis limits limits = get(ax, 'ZLim'); zticks = linspace(limits(1), limits(2), new_num_ticks); zticks_labels = num2str(zticks(:), '%.2f ($)'); % update ticks set(ax, 'ZTick',zticks, 'ZTickLabel',zticks_labels) drawnow end

The idea is to create a hidden copy axis synchronized with the original during 3D rotation. This second axis will have automatic tick marks, while we adjust the ticks of the first axis as we see fit (similar to how we register a callback on a hidden axis when ticks change).
Again, I use this hidden axis to let MATLAB handle the task of determining the best number of ticks, given the view (this is much easier than messing around with camera angles and matrix transformations to find out the length of the projected axis in pixels).
In the above example, I just set the number of ticks to one less than the automatic number ( {2,4,10} instead of {3,5,11} ), but you can use any matching you want.